diff --git a/git-teaspeak b/git-teaspeak index 6dd8f87..2c92822 160000 --- a/git-teaspeak +++ b/git-teaspeak @@ -1 +1 @@ -Subproject commit 6dd8f87281e6fd60df0c5babfc1303df74ce1c0a +Subproject commit 2c928229b1aab0306a02d2b7820fd93f3a3623b9 diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 9849899..83b84cb 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -227,7 +227,7 @@ target_link_libraries(PermMapHelper SET(CPACK_PACKAGE_VERSION_MAJOR "1") SET(CPACK_PACKAGE_VERSION_MINOR "3") -SET(CPACK_PACKAGE_VERSION_PATCH "24") +SET(CPACK_PACKAGE_VERSION_PATCH "25") if(BUILD_TYPE_NAME EQUAL OFF) SET(CPACK_PACKAGE_VERSION_DATA "beta") elseif(BUILD_TYPE_NAME STREQUAL "") diff --git a/server/src/Group.cpp b/server/src/Group.cpp index 0ad8965..6805061 100644 --- a/server/src/Group.cpp +++ b/server/src/Group.cpp @@ -171,7 +171,7 @@ int GroupManager::insertGroupFromDb(int count, char **values, char **column) { else cerr << "Invalid group table row " << column[index] << endl; } - if(groupId == 0 || target == 0xff || type == 0xff || targetName.empty()) { + if((size_t) groupId == 0 || (size_t) target == 0xff || (size_t) type == 0xff || targetName.empty()) { logCritical(this->getServerId(), "Found invalid group ad database! (GroupId " + to_string(groupId) + ", Target " + to_string(target) + ", Type " + to_string(type) + ", Name '" + targetName + "')"); return 0; } @@ -225,11 +225,15 @@ int GroupManager::insertGroupFromDb(int count, char **values, char **column) { return 0; } -void GroupManager::handleChannelDeleted(std::shared_ptr channel) { - cacheLock.lock(); - for(const auto &entry : this->cachedClients) - entry->channelGroups.erase(channel->channelId()); - cacheLock.unlock(); +void GroupManager::handleChannelDeleted(const ChannelId& channel_id) { + unique_lock cache_lock(this->cacheLock); + auto cached_clients = std::vector>{this->cachedClients.begin(), this->cachedClients.end()}; + cache_lock.unlock(); + + for(auto& entry : cached_clients) { + lock_guard entry_lock(entry->lock); + entry->channel_groups.erase(channel_id); + } } bool GroupManager::isLocalGroup(std::shared_ptr gr) { @@ -373,24 +377,11 @@ bool GroupManager::deleteAllGroups() { LOG_SQL_CMD(sql::command(this->sql, "DELETE FROM `assignedGroups` WHERE `serverId` = :sid", variable{":sid", this->getServerId()}).execute()); LOG_SQL_CMD(sql::command(this->sql, "DELETE FROM `permissions` WHERE `serverId` = :sid AND `type` = :type", variable{":sid", this->getServerId()}, variable{":type", SQL_PERM_GROUP}).execute()); { - threads::MutexLock lock(this->cacheLock); + lock_guard cache_lock(this->cacheLock); for(const auto& entry : this->cachedClients) { - threads::MutexLock lock_entry(entry->lock); - bool iterate = true; - while(iterate) { - iterate = false; - for(const auto& assignment : entry->channelGroups) { - if(std::find(this->groups.begin(), this->groups.end(), assignment.second->group) != this->groups.end()) { - entry->channelGroups.erase(assignment.first); - iterate = true; - break; - } - } - } - - entry->serverGroups.erase(std::remove_if(entry->serverGroups.begin(), entry->serverGroups.end(), [&](const shared_ptr& assignment){ - return std::find(this->groups.begin(), this->groups.end(), assignment->group) != this->groups.end(); - }), entry->serverGroups.end()); + lock_guard entry_lock(entry->lock); + entry->server_groups.clear(); + entry->channel_groups.clear(); } } this->groups.clear(); @@ -405,6 +396,25 @@ bool GroupManager::deleteGroup(std::shared_ptr group) { this->groups.erase(std::find(this->groups.begin(), this->groups.end(), group)); + /* erase the group out of our cache */ + { + lock_guard cache_lock(this->cacheLock); + for(auto& entry : this->cachedClients) { + lock_guard entry_lock(entry->lock); + + entry->server_groups.erase(std::remove_if(entry->server_groups.begin(), entry->server_groups.end(), [&](const std::shared_ptr& group_assignment) { + return group_assignment->group == group; + }), entry->server_groups.end()); + + for(auto it = entry->channel_groups.begin(); it != entry->channel_groups.end();) { + if(it->second->group == group) + it = entry->channel_groups.erase(it); + else + it++; + } + } + } + bool flag_sql = false; auto res = sql::command(this->sql, "DELETE FROM `groups` WHERE `serverId` = :sid AND `groupId` = :gid", variable{":sid", this->getServerId()}, variable{":gid", group->groupId()}).execute(); LOG_SQL_CMD(res); @@ -418,33 +428,6 @@ bool GroupManager::deleteGroup(std::shared_ptr group) { if(flag_sql) logError(this->getServerId(), "Could not delete group {} ({}) from database. May leader to invalid data", group->name(), group->groupId()); - this->cacheLock.lock(); - for(const auto &entry : this->cachedClients){ - bool iterate = true; - while(iterate) { - iterate = false; - for(const auto &assignment : entry->serverGroups){ - if(assignment->group == group){ - entry->serverGroups.erase(std::find(entry->serverGroups.begin(), entry->serverGroups.end(), assignment)); - iterate = true; - break; - } - } - - } - iterate = true; - while(iterate) { - iterate = false; - for(const auto& pair : entry->channelGroups){ - if(pair.second->group == group){ - entry->channelGroups.erase(pair.first); - iterate = true; - break; - } - } - } - } - this->cacheLock.unlock(); return true; } @@ -515,95 +498,93 @@ void GroupManager::cleanupAssignments(ClientDbId client) { } } -template -struct DBLoadCacheParmStruct { - GroupManager* manager; - DataType* data; -}; - -void GroupManager::enableCache(std::shared_ptr client) { +void GroupManager::enableCache(const ClientDbId& client_database_id) { if(this->root) - this->root->enableCache(client); + this->root->enableCache(client_database_id); - shared_ptr entry = std::make_shared(); - entry->client = client; + unique_lock cache_lock(this->cacheLock); + /* test if we're already having the client */ + for(auto& entry : this->cachedClients) + if(entry->client_database_id == client_database_id) { + entry->use_count++; + return; /* client already cached, no need to cache client */ + } - DBLoadCacheParmStruct parm = {this, entry.get()}; + auto entry = std::make_shared(); + entry->client_database_id = client_database_id; + entry->use_count++; + this->cachedClients.push_back(entry); - auto res = sql::command(this->sql, "SELECT `groupId`, `channelId`, `until` FROM `assignedGroups` WHERE `serverId` = :sid AND `cldbid` = :cldbid", variable{":sid", this->getServerId()}, variable{":cldbid", client->getClientDatabaseId()}).query([&](DBLoadCacheParmStruct* parms, int length, char** value, char** column) { + lock_guard client_cache_lock(entry->lock); /* lock the client because we're currently loading the cache. */ + cache_lock.unlock(); + + auto res = sql::command(this->sql, "SELECT `groupId`, `channelId`, `until` FROM `assignedGroups` WHERE `serverId` = :sid AND `cldbid` = :cldbid", variable{":sid", this->getServerId()}, variable{":cldbid", client_database_id}) + .query([&](int length, std::string* value, std::string* column) { shared_ptr group = nullptr; time_point until; ChannelId channelId = 0; for(int index = 0; index < length; index++){ - if(value[index] == nullptr) { - logError(this->getServerId(), string() + "Invalid value at " + column[index]); - continue; + try { + if(column[index] == "groupId"){ + group = this->findGroup(stoll(value[index])); + } else if(column[index] == "until"){ + until = time_point() + milliseconds(stoll(value[index])); + } else if(column[index] == "channelId"){ + channelId = stoll(value[index]); + } else { + logError(this->getServerId(), "Unknown column in group assignment query: {}", column[index]); + continue; + } + } catch(std::exception& ex) { + logError(this->getServerId(), "Failed to load group assignment from database for client {}. Column {} contains an invalid value: {}", client_database_id, column[index], value[index]); + return 0; } - if(strcmp(column[index], "groupId") == 0){ - group = parms->manager->findGroup(stoll(value[index])); - } else if(strcmp(column[index], "until") == 0){ - until = time_point() + milliseconds(stoll(value[index])); - } else if(strcmp(column[index], "channelId") == 0){ - channelId = stoll(value[index]); - } else cerr << "Invalid column " << column[index] << endl; } - if(!group) - return 0; + if(!group) { + return 0; + } - shared_ptr assignment = std::make_shared(); + auto assignment = std::make_shared(); assignment->group = group; assignment->until = until; - assignment->parent = parms->data; + assignment->parent = &*entry; assignment->channelId = channelId; assignment->server = this->getServerId(); - if(channelId == 0) - parms->data->serverGroups.push_back(assignment); - else parms->data->channelGroups[channelId] = assignment; - return 0; - }, &parm); - this->cacheLock.lock(); - this->cachedClients.push_back(entry); - this->cacheLock.unlock(); + if(channelId == 0) + entry->server_groups.push_back(assignment); + else + entry->channel_groups[channelId] = assignment; + return 0; + }); } -void GroupManager::disableCache(const shared_ptr &client) { - if(this->root) this->root->disableCache(client); +//FIXME: This method till get far more often then it should be. We should add a flag if the group cache is loaded for each std::shared_ptr instance +void GroupManager::disableCache(const ClientDbId& client_database_id) { + if(this->root) + this->root->disableCache(client_database_id); - threads::MutexLock lock(this->cacheLock); - bool found = false; - for(const auto& entry : this->cachedClients){ - if(entry->client == client){ - this->cachedClients.erase(std::find(this->cachedClients.begin(), this->cachedClients.end(), entry)); - found = true; - break; - } - } - if(!found) - ;//debugMessage("Tried to attempt to delete a not existing cached manager. (" + manager->getDisplayName() + ")"); + lock_guard cache_lock(this->cacheLock); + this->cachedClients.erase(std::remove_if(this->cachedClients.begin(), this->cachedClients.end(), [&](const std::shared_ptr& client) { + if(client->client_database_id != client_database_id) + return false; + + lock_guard client_lock{client->lock}; + return (--client->use_count) == 0; + }), this->cachedClients.end()); } void GroupManager::clearCache() { if(this->root) this->root->clearCache(); - threads::MutexLock lock(cacheLock); + lock_guard lock(this->cacheLock); this->cachedClients.clear(); } -bool GroupManager::isClientCached(const shared_ptr &client) { - { - threads::MutexLock lock(cacheLock); - for(const auto &entry : this->cachedClients){ - if(entry->client == client){ - return true; - } - } - } - - if(this->root) return this->root->isClientCached(client); - return false; +bool GroupManager::isClientCached(const ClientDbId& client_database_id) { + return this->resolve_cached_client(client_database_id) == nullptr; } typedef std::vector> ResList; @@ -644,19 +625,17 @@ std::vector> GroupManager::listGroupMembers(std::sh return result; } -typedef DBLoadCacheParmStruct>> GAGroupCache; vector> GroupManager::listGroupAssignments(ClientDbId cldbId) { vector> result; - GAGroupCache parm = {this, &result}; sql::result res; - auto cached = resolveCached(cldbId); + auto cached = resolve_cached_client(cldbId); if(cached) { { - threads::MutexLock l(cached->lock); - for(const auto &serverGroup : cached->serverGroups) + lock_guard lock{cached->lock}; + for(const auto &serverGroup : cached->server_groups) result.push_back(serverGroup); - for(auto& channelGroup : cached->channelGroups) + for(auto& channelGroup : cached->channel_groups) result.push_back(channelGroup.second); } @@ -670,7 +649,8 @@ vector> GroupManager::listGroupAssignments(ClientDbI } - res = sql::command(this->sql, "SELECT `groupId`, `until`, `channelId` FROM `assignedGroups` WHERE `serverId` = :sid AND `cldbid` = :cldbid", variable{":sid", this->getServerId()}, variable{":cldbid", cldbId}).query([&](GAGroupCache* parms, int length, char** value, char** column){ + res = sql::command(this->sql, "SELECT `groupId`, `until`, `channelId` FROM `assignedGroups` WHERE `serverId` = :sid AND `cldbid` = :cldbid", variable{":sid", this->getServerId()}, variable{":cldbid", cldbId}) + .query([&](int length, char** value, char** column){ shared_ptr group = nullptr; time_point until; uint64_t channelId = 0; @@ -681,7 +661,7 @@ vector> GroupManager::listGroupAssignments(ClientDbI continue; } if(strcmp(column[index], "groupId") == 0){ - group = parms->manager->findGroup(stoll(value[index])); + group = this->findGroup(stoll(value[index])); } else if(strcmp(column[index], "until") == 0){ until = time_point() + milliseconds(stoll(value[index])); } else if(strcmp(column[index], "channelId") == 0){ @@ -697,9 +677,9 @@ vector> GroupManager::listGroupAssignments(ClientDbI assignment->until = until; assignment->channelId = channelId; assignment->server = this->getServerId(); - parms->data->push_back(assignment); + result.push_back(assignment); return 0; - }, &parm); + }); (LOG_SQL_CMD)(res); if(this->root){ @@ -711,18 +691,19 @@ vector> GroupManager::listGroupAssignments(ClientDbI return result; } -std::shared_ptr GroupManager::resolveCached(ClientDbId cldbId) { - threads::MutexLock lock(this->cacheLock); - for(const auto& cl : this->cachedClients) - if(cl->client->getClientDatabaseId() == cldbId){ - return cl; - } - return nullptr; +std::shared_ptr GroupManager::resolve_cached_client(ClientDbId client_database_id) { + { + lock_guard lock(this->cacheLock); + for(auto& entry : this->cachedClients) + if(entry->client_database_id == client_database_id) + return entry; + } + + return nullptr; } -typedef DBLoadCacheParmStruct>> SGroupCache; std::vector> GroupManager::getAssignedServerGroups(ClientDbId cldbid) { - auto cached = this->resolveCached(cldbid); + auto cached = this->resolve_cached_client(cldbid); sql::result res; std::vector> result; if(this->root) { @@ -730,17 +711,15 @@ std::vector> GroupManager::getAssignedServerGro result.insert(result.begin(), root.begin(), root.end()); } - SGroupCache parm = {this, &result}; - if(cached) { - threads::MutexLock l(cached->lock); - for(const auto &elm : cached->serverGroups) result.push_back(elm); + lock_guard cache_lock{cached->lock}; + result.insert(result.end(), cached->server_groups.begin(), cached->server_groups.end()); return result; } debugMessage("DB query groups! for -> " + to_string(cldbid) + " - server " + to_string(this->getServerId())); - res = sql::command(this->sql, "SELECT `groupId`, `until` FROM `assignedGroups` WHERE `serverId` = :sid AND `cldbid` = :cldbid AND `channelId` = 0", variable{":sid", this->getServerId()}, variable{":cldbid", cldbid}).query([&](SGroupCache* parms, int length, char** value, char** column){ + res = sql::command(this->sql, "SELECT `groupId`, `until` FROM `assignedGroups` WHERE `serverId` = :sid AND `cldbid` = :cldbid AND `channelId` = 0", variable{":sid", this->getServerId()}, variable{":cldbid", cldbid}).query([&](int length, char** value, char** column){ shared_ptr group = nullptr; time_point until; @@ -750,7 +729,7 @@ std::vector> GroupManager::getAssignedServerGro continue; } if(strcmp(column[index], "groupId") == 0 && value[index] != nullptr){ - group = parms->manager->findGroup(stoll(value[index])); + group = this->findGroup(stoll(value[index])); } else if(strcmp(column[index], "until") == 0){ until = time_point() + milliseconds(stoll(value[index] == nullptr ? "0" : value[index])); } else cerr << "Invalid column " << column[index] << endl; @@ -763,9 +742,9 @@ std::vector> GroupManager::getAssignedServerGro assignment->group = group; assignment->until = until; assignment->server = this->getServerId(); - parms->data->push_back(assignment); + result.push_back(assignment); return 0; - }, &parm); + }); LOG_SQL_CMD(res); return result; } @@ -799,20 +778,18 @@ std::vector> GroupManager::defaultServerGroupGr return result; } -typedef DBLoadCacheParmStruct> CGroupCache; std::shared_ptr GroupManager::getChannelGroupExact(ClientDbId cldbId, const std::shared_ptr& channel, bool assign_default) { - auto cached = resolveCached(cldbId); + auto cached = resolve_cached_client(cldbId); if(cached) { - threads::MutexLock l(cached->lock); - if(cached->channelGroups.count(channel->channelId()) > 0) { - return cached->channelGroups[channel->channelId()]; + lock_guard cache_lock(cached->lock); + if(cached->channel_groups.count(channel->channelId()) > 0) { + return cached->channel_groups[channel->channelId()]; } else return assign_default ? this->defaultChannelGroupAssignment(cldbId, channel) : nullptr; } std::shared_ptr result; - CGroupCache parm = {this, &result}; - auto res = sql::command(this->sql, "SELECT `groupId`, `until` FROM `assignedGroups` WHERE `serverId` = :sid AND `cldbid` = :cldbid AND `channelId` = :chid", variable{":sid", this->getServerId()}, variable{":cldbid", cldbId}, variable{":chid", channel->channelId()}).query([&](CGroupCache* parms, int length, char** value, char** column){ + auto res = sql::command(this->sql, "SELECT `groupId`, `until` FROM `assignedGroups` WHERE `serverId` = :sid AND `cldbid` = :cldbid AND `channelId` = :chid", variable{":sid", this->getServerId()}, variable{":cldbid", cldbId}, variable{":chid", channel->channelId()}).query([&](int length, char** value, char** column){ shared_ptr group = nullptr; time_point until; @@ -822,7 +799,7 @@ std::shared_ptr GroupManager::getChannelGroupExact(ClientDbId c continue; } if(strcmp(column[index], "groupId") == 0){ - group = parms->manager->findGroup(stoll(value[index])); + group = this->findGroup(stoll(value[index])); } else if(strcmp(column[index], "until") == 0){ until = time_point() + milliseconds(stoll(value[index])); } else cerr << "Invalid column " << column[index] << endl; @@ -836,9 +813,9 @@ std::shared_ptr GroupManager::getChannelGroupExact(ClientDbId c assignment->until = until; assignment->server = this->getServerId(); assignment->channelId = channel->channelId(); - *parms->data = assignment; + result = std::move(assignment); return 0; - }, &parm); + }); (LOG_SQL_CMD)(res); return !result && assign_default ? this->defaultChannelGroupAssignment(cldbId, channel) : result; @@ -873,10 +850,10 @@ void GroupManager::addServerGroup(ClientDbId cldbId, std::shared_ptr grou if(hasServerGroup(cldbId, group)) return; */ - auto cached = resolveCached(cldbId); + auto cached = resolve_cached_client(cldbId); if(cached) { - threads::MutexLock l(cached->lock); - cached->serverGroups.push_back(std::make_shared(cached.get(), this->getServerId(), 0, group, until)); + lock_guard cache_lock(cached->lock); + cached->server_groups.push_back(std::make_shared(cached.get(), this->getServerId(), 0, group, until)); } sql::command(this->sql, "INSERT INTO `assignedGroups` (`serverId`, `cldbid`, `groupId`, `channelId`, `until`) VALUES (:sid, :cldbid, :gid, :chid, :until)", @@ -890,14 +867,12 @@ void GroupManager::addServerGroup(ClientDbId cldbId, std::shared_ptr grou void GroupManager::removeServerGroup(ClientDbId cldbId, std::shared_ptr group) { if(!this->hasServerGroupAssigned(cldbId, group)) return; - auto cached = resolveCached(cldbId); + auto cached = resolve_cached_client(cldbId); if(cached) { - threads::MutexLock l(cached->lock); - for(const auto &entry : cached->serverGroups) - if(entry->group == group){ - cached->serverGroups.erase(std::find(cached->serverGroups.begin(), cached->serverGroups.end(), entry)); - break; - } + lock_guard cache_lock(cached->lock); + cached->server_groups.erase(std::remove_if(cached->server_groups.begin(), cached->server_groups.end(), [&](const std::shared_ptr& group_assignment) { + return group_assignment->group == group; + }), cached->server_groups.end()); } sql::command(this->sql, "DELETE FROM `assignedGroups` WHERE `serverId` = :sid AND `cldbid` = :cldbid AND `groupId` = :gid AND `channelId` = :chid", @@ -915,13 +890,13 @@ void GroupManager::setChannelGroup(ClientDbId cldbId, std::shared_ptr gro } else if(!group) return; auto default_group = !group || group == this->defaultGroup(GroupTarget::GROUPTARGET_CHANNEL); - auto cached = resolveCached(cldbId); + auto cached = resolve_cached_client(cldbId); if(cached) { - threads::MutexLock l(cached->lock); + lock_guard cache_lock(cached->lock); if(default_group) - cached->channelGroups.erase(channel->channelId()); + cached->channel_groups.erase(channel->channelId()); else - cached->channelGroups[channel->channelId()] = std::make_shared(cached.get(), this->getServerId(), channel->channelId(), group, until); + cached->channel_groups[channel->channelId()] = std::make_shared(cached.get(), this->getServerId(), channel->channelId(), group, until); } sql::command(this->sql, "DELETE FROM `assignedGroups` WHERE `serverId` = :sid AND `cldbid` = :cldbid AND `channelId` = :chid", diff --git a/server/src/Group.h b/server/src/Group.h index 1bd5809..99b5a4c 100644 --- a/server/src/Group.h +++ b/server/src/Group.h @@ -17,7 +17,7 @@ namespace ts { class ConnectedClient; } - class CachedClient; + struct CachedClient; class GroupManager; class Group; @@ -66,10 +66,14 @@ namespace ts { }; struct CachedClient { - std::shared_ptr client; - std::vector> serverGroups; - std::map> channelGroups; - threads::Mutex lock; + ClientDbId client_database_id; + + std::vector> server_groups; + std::map> channel_groups; + + size_t use_count = 0; + + std::mutex lock; /* never lock this lock before the general client cache! */ }; class Group { @@ -160,6 +164,12 @@ namespace ts { return false; } + std::shared_ptr get_group_assignment(const ClientDbId& client_database_id, const std::shared_ptr& group) { + for(const auto& assign : this->getAssignedServerGroups(client_database_id)) + if(assign->group == group) return assign; + return nullptr; + } + std::vector> getServerGroups(ClientDbId cldbid, server::ClientType type); inline bool hasServerGroup(uint64_t cldbId, server::ClientType type, const std::shared_ptr& group){ for(const auto& assign : this->getServerGroups(cldbId, type)) if(assign->group == group) return true; @@ -200,15 +210,15 @@ namespace ts { std::shared_ptr defaultGroup(GroupTarget type, bool enforce_property = false); std::deque update_server_group_property(const std::shared_ptr &client, bool channel_lock); - void enableCache(std::shared_ptr client); - void disableCache(const std::shared_ptr &client); - bool isClientCached(const std::shared_ptr &client); + void enableCache(const ClientDbId& /* client database id */); /* if this called disableCache(...) MUST be called to decrease the reference count */ + void disableCache(const ClientDbId& /* client database id */); + bool isClientCached(const ClientDbId& /* client database id */); void clearCache(); bool isLocalGroup(std::shared_ptr); protected: - void handleChannelDeleted(std::shared_ptr ); + void handleChannelDeleted(const ChannelId& /* channel id */); private: std::shared_ptr root = nullptr; std::weak_ptr server; @@ -221,6 +231,6 @@ namespace ts { int insertGroupFromDb(int count, char** values, char** column); - inline std::shared_ptr resolveCached(ClientDbId cldbId); + inline std::shared_ptr resolve_cached_client(ClientDbId client_database_id); }; } \ No newline at end of file diff --git a/server/src/channel/ServerChannel.cpp b/server/src/channel/ServerChannel.cpp index 5ee17a4..c084c50 100644 --- a/server/src/channel/ServerChannel.cpp +++ b/server/src/channel/ServerChannel.cpp @@ -531,9 +531,9 @@ void ServerChannelTree::on_channel_entry_deleted(const shared_ptr auto server = this->server.lock(); if(server) - server->getGroupManager()->handleChannelDeleted(channel); + server->getGroupManager()->handleChannelDeleted(channel->channelId()); else - serverInstance->getGroupManager()->handleChannelDeleted(channel); + serverInstance->getGroupManager()->handleChannelDeleted(channel->channelId()); auto sql_result = sql::command(this->sql, "DELETE FROM `channels` WHERE `serverId` = '" + to_string(this->getServerId()) + "' AND `channelId` = '" + to_string(channel->channelId()) + "'").execute(); diff --git a/server/src/client/ConnectedClientCommandHandler.cpp b/server/src/client/ConnectedClientCommandHandler.cpp index 4c42564..162c769 100644 --- a/server/src/client/ConnectedClientCommandHandler.cpp +++ b/server/src/client/ConnectedClientCommandHandler.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include namespace fs = std::experimental::filesystem; @@ -184,8 +185,8 @@ CommandResult ConnectedClient::handleCommand(Command &cmd) { else if (command == "servergroupdel") return this->handleCommandServerGroupDel(cmd); else if (command == "servergrouprename") return this->handleCommandServerGroupRename(cmd); else if (command == "servergroupclientlist") return this->handleCommandServerGroupClientList(cmd); - else if (command == "servergroupaddclient") return this->handleCommandServerGroupAddClient(cmd); - else if (command == "servergroupdelclient") return this->handleCommandServerGroupDelClient(cmd); + else if (command == "servergroupaddclient" || command == "clientaddservergroup") return this->handleCommandServerGroupAddClient(cmd); + else if (command == "servergroupdelclient" || command == "clientdelservergroup") return this->handleCommandServerGroupDelClient(cmd); else if (command == "servergrouppermlist") return this->handleCommandServerGroupPermList(cmd); else if (command == "servergroupaddperm") return this->handleCommandServerGroupAddPerm(cmd); else if (command == "servergroupdelperm") return this->handleCommandServerGroupDelPerm(cmd); @@ -2668,39 +2669,107 @@ CommandResult ConnectedClient::handleCommandServerGroupAddClient(Command &cmd) { CMD_RESET_IDLE; CMD_CHK_AND_INC_FLOOD_POINTS(25); - auto server = cmd[0].has("sid") && cmd["sid"] == 0 ? nullptr : this->server; - auto groupManager = server ? this->server->groups : serverInstance->getGroupManager().get(); - auto serverGroup = groupManager->findGroup(cmd["sgid"].as()); - if (!serverGroup) return {findError("parameter_invalid"), "invalid server group id"}; - if((server != this->server || !this->server) && serverGroup->target() != GroupTarget::GROUPTARGET_SERVER && serverGroup->type() != GroupType::GROUP_TYPE_QUERY) return {findError("parameter_invalid"), "invalid group type"}; + auto target_server = cmd[0].has("sid") && cmd["sid"] == 0 ? nullptr : this->server; + auto group_manager = target_server ? this->server->groups : serverInstance->getGroupManager().get(); auto target_cldbid = cmd["cldbid"].as(); - { - if(!serverGroup->permission_granted(permission::i_server_group_needed_member_add_power, this->calculate_permission_value(permission::i_server_group_member_add_power, -1), true)) { - if(target_cldbid != this->getClientDatabaseId()) - return CommandResultPermissionError{permission::i_server_group_member_add_power}; - if(!serverGroup->permission_granted(permission::i_server_group_needed_member_add_power, this->calculate_permission_value(permission::i_server_group_self_add_power, -1), true)) - return CommandResultPermissionError{permission::i_server_group_self_add_power}; - } + if (!serverInstance->databaseHelper()->validClientDatabaseId(target_server, cmd["cldbid"])) return {findError("client_invalid_id"), "invalid cldbid"}; - auto needed_client_permission = this->server->calculatePermission(permission::PERMTEST_ORDERED, target_cldbid, permission::i_client_needed_permission_modify_power, ClientType::CLIENT_TEAMSPEAK,nullptr); - if(needed_client_permission != permNotGranted) { - if(!this->permission_granted(this->permissionValue(permission::i_client_permission_modify_power), needed_client_permission)) - return CommandResultPermissionError{permission::i_client_needed_permission_modify_power}; + auto needed_client_permission = this->server->calculatePermission(permission::PERMTEST_ORDERED, target_cldbid, permission::i_client_needed_permission_modify_power, ClientType::CLIENT_TEAMSPEAK, nullptr); + if(needed_client_permission != permNotGranted) { + if(!this->permission_granted(this->permissionValue(permission::i_client_permission_modify_power), needed_client_permission)) + return CommandResultPermissionError{permission::i_client_needed_permission_modify_power}; + } + + vector> target_groups; + vector> applied_groups; + target_groups.reserve(cmd.bulkCount()); + + auto continue_on_error = cmd.hasParm("continueonerror"); + { + auto permission_add_power = this->calculate_permission_value(permission::i_server_group_member_add_power, -1); + auto permission_self_add_power = this->calculate_permission_value(permission::i_server_group_member_add_power, -1); + + for(auto index = 0; index < cmd.bulkCount(); index++) { + auto group_id = cmd[index]["sgid"]; + if(!group_id.castable() && continue_on_error) + continue; + + auto gid = group_id.as(); + auto group = group_manager->findGroup(gid); + if(!group) { + if(continue_on_error) + continue; + + return {findError("parameter_invalid"), "missing server group for id " + to_string(gid)}; + } + + if(!target_server && group->target() != GroupTarget::GROUPTARGET_SERVER && group->type() != GroupType::GROUP_TYPE_QUERY) + return {findError("parameter_invalid"), "invalid server group type for id " + to_string(gid)}; + + if(find(target_groups.begin(), target_groups.end(), group) != target_groups.end()) { + if(continue_on_error) + continue; + + return {findError("parameter_invalid"), "duplicate server group for id " + to_string(gid)}; + } + + /* permission tests */ + if(!group->permission_granted(permission::i_server_group_needed_member_add_power, permission_add_power, true)) { + if(target_cldbid != this->getClientDatabaseId()) { + if(continue_on_error) + continue; + + return CommandResultPermissionError{permission::i_server_group_member_add_power}; + } + + if(!group->permission_granted(permission::i_server_group_needed_member_add_power, permission_self_add_power, true)) { + if(continue_on_error) + continue; + + return CommandResultPermissionError{permission::i_server_group_self_add_power}; + } + } + + target_groups.push_back(std::move(group)); } } - if (!serverInstance->databaseHelper()->validClientDatabaseId(server, cmd["cldbid"])) return {findError("client_invalid_id"), "invalid cldbid"}; - if(groupManager->hasServerGroupAssigned(cmd["cldbid"], serverGroup)) return {findError("parameter_invalid"), "Client is already member of this group"}; + applied_groups.reserve(target_groups.size()); + if(target_groups.empty()) return CommandResult::Success; + else if(target_groups.size() == 1) { + /* speed up thing, don't try to load any cache */ + auto group = target_groups[0]; + if(group_manager->hasServerGroupAssigned(target_cldbid, group)) + return {findError("parameter_invalid"), "Client is already member of server group " + to_string(group->groupId())}; - groupManager->addServerGroup(target_cldbid, serverGroup); + group_manager->addServerGroup(target_cldbid, group); + applied_groups.push_back(group); + } else { + group_manager->enableCache(target_cldbid); + scope_exit_callback cache_disable{[group_manager, target_cldbid]{ + group_manager->disableCache(target_cldbid); + }}; - for(const auto& _server : server ? std::deque>{server} : serverInstance->getVoiceServerManager()->serverInstances()) { + for(const auto& group : target_groups) { + if(group_manager->hasServerGroupAssigned(target_cldbid, group)) { + if(continue_on_error) + continue; + return {findError("parameter_invalid"), "Client is already member of server group " + to_string(group->groupId())}; + } + + group_manager->addServerGroup(target_cldbid, group); + applied_groups.push_back(group); + } + } + + for(const auto& _server : target_server ? std::deque>{target_server} : serverInstance->getVoiceServerManager()->serverInstances()) { for (const auto &targetClient : _server->findClientsByCldbId(target_cldbid)) { - if (_server->notifyClientPropertyUpdates(targetClient, _server->groups->update_server_group_property(targetClient,true))) { + if (_server->notifyClientPropertyUpdates(targetClient, _server->groups->update_server_group_property(targetClient, true))) { for (const auto &client : _server->getClients()) { if(client->isClientVisible(targetClient, true) || client == targetClient) - client->notifyServerGroupClientAdd(_this.lock(), targetClient, serverGroup); + for(const auto& group : applied_groups) + client->notifyServerGroupClientAdd(_this.lock(), targetClient, group); } if(targetClient->update_cached_permissions()) /* update cached calculated permissions */ targetClient->sendNeededPermissions(false); /* cached permissions had changed, notify the client */ @@ -2713,53 +2782,130 @@ CommandResult ConnectedClient::handleCommandServerGroupAddClient(Command &cmd) { } CommandResult ConnectedClient::handleCommandServerGroupDelClient(Command &cmd) { - CMD_RESET_IDLE; - CMD_CHK_AND_INC_FLOOD_POINTS(25); + CMD_RESET_IDLE; + CMD_CHK_AND_INC_FLOOD_POINTS(25); - auto server = cmd[0].has("sid") && cmd["sid"] == 0 ? nullptr : this->server; - auto groupManager = server ? this->server->groups : serverInstance->getGroupManager().get(); - auto serverGroup = groupManager->findGroup(cmd["sgid"].as()); - if (!serverGroup) return {findError("parameter_invalid"), "invalid server group id"}; - if((server != this->server || !this->server) && serverGroup->target() != GroupTarget::GROUPTARGET_SERVER && serverGroup->type() != GroupType::GROUP_TYPE_QUERY) return {findError("parameter_invalid"), "invalid group type"}; + auto target_server = cmd[0].has("sid") && cmd["sid"] == 0 ? nullptr : this->server; + auto group_manager = target_server ? this->server->groups : serverInstance->getGroupManager().get(); auto target_cldbid = cmd["cldbid"].as(); - { - if(!serverGroup->permission_granted(permission::i_server_group_needed_member_remove_power, this->calculate_permission_value(permission::i_server_group_member_remove_power, -1), true)) { - if(target_cldbid != this->getClientDatabaseId()) - return CommandResultPermissionError{permission::i_server_group_member_remove_power}; - if(!serverGroup->permission_granted(permission::i_server_group_needed_member_remove_power, this->calculate_permission_value(permission::i_server_group_self_remove_power, -1), true)) - return CommandResultPermissionError{permission::i_server_group_self_remove_power}; - } + if (!serverInstance->databaseHelper()->validClientDatabaseId(target_server, cmd["cldbid"])) return {findError("client_invalid_id"), "invalid cldbid"}; - auto needed_client_permission = this->server->calculatePermission(permission::PERMTEST_ORDERED, target_cldbid, permission::i_client_needed_permission_modify_power, ClientType::CLIENT_TEAMSPEAK,nullptr); - if(needed_client_permission != permNotGranted) { - if(!this->permission_granted(this->permissionValue(permission::i_client_permission_modify_power), needed_client_permission)) - return CommandResultPermissionError{permission::i_client_needed_permission_modify_power}; + auto needed_client_permission = this->server->calculatePermission(permission::PERMTEST_ORDERED, target_cldbid, permission::i_client_needed_permission_modify_power, ClientType::CLIENT_TEAMSPEAK, nullptr); + if(needed_client_permission != permNotGranted) { + if(!this->permission_granted(this->permissionValue(permission::i_client_permission_modify_power), needed_client_permission)) + return CommandResultPermissionError{permission::i_client_needed_permission_modify_power}; + } + + vector> target_groups; + vector> applied_groups; + target_groups.reserve(cmd.bulkCount()); + + auto continue_on_error = cmd.hasParm("continueonerror"); + { + auto permission_remove_power = this->calculate_permission_value(permission::i_server_group_member_remove_power, -1); + auto permission_self_remove_power = this->calculate_permission_value(permission::i_server_group_member_remove_power, -1); + + for(auto index = 0; index < cmd.bulkCount(); index++) { + auto group_id = cmd[index]["sgid"]; + if(!group_id.castable() && continue_on_error) + continue; + + auto gid = group_id.as(); + auto group = group_manager->findGroup(gid); + if(!group) { + if(continue_on_error) + continue; + + return {findError("parameter_invalid"), "missing server group for id " + to_string(gid)}; + } + + if(!target_server && group->target() != GroupTarget::GROUPTARGET_SERVER && group->type() != GroupType::GROUP_TYPE_QUERY) + return {findError("parameter_invalid"), "invalid server group type for id " + to_string(gid)}; + + if(find(target_groups.begin(), target_groups.end(), group) != target_groups.end()) { + if(continue_on_error) + continue; + + return {findError("parameter_invalid"), "duplicate server group for id " + to_string(gid)}; + } + + /* permission tests */ + if(!group->permission_granted(permission::i_server_group_needed_member_remove_power, permission_remove_power, true)) { + if(target_cldbid != this->getClientDatabaseId()) { + if(continue_on_error) + continue; + + return CommandResultPermissionError{permission::i_server_group_member_remove_power}; + } + + if(!group->permission_granted(permission::i_server_group_needed_member_remove_power, permission_self_remove_power, true)) { + if(continue_on_error) + continue; + + return CommandResultPermissionError{permission::i_server_group_self_remove_power}; + } + } + + target_groups.push_back(std::move(group)); } } - if (!serverInstance->databaseHelper()->validClientDatabaseId(server, cmd["cldbid"])) return {findError("client_invalid_id"), "invalid cldbid"}; - if(!groupManager->hasServerGroupAssigned(cmd["cldbid"], serverGroup)) return {findError("parameter_invalid"), "Client isn't a member of this group"}; - for(const auto& assignment : groupManager->listGroupAssignments(cmd["cldbid"])) - if(assignment->group == serverGroup && assignment->server != this->getServerId()) return {findError("parameter_invalid"), "Group wasn't assigned over this server (Assigned server: " + to_string(assignment->server) + ")"}; + applied_groups.reserve(target_groups.size()); + if(target_groups.empty()) return CommandResult::Success; + else if(target_groups.size() == 1) { + /* speed up thing, don't try to load any cache */ + auto group = target_groups[0]; + auto assignment = group_manager->get_group_assignment(target_cldbid, group); + if(!assignment) { + return {findError("parameter_invalid"), "Client is not member of server group " + to_string(group->groupId())}; + } + if(assignment->server != (target_server ? target_server->getServerId() : 0)) { + return {findError("parameter_invalid"), "Group assignment for group " + to_string(assignment->group->groupId()) + " hasn't been made over the target server. Assignment origin server id " + to_string(assignment->server)}; + } - groupManager->removeServerGroup(target_cldbid, serverGroup); + group_manager->removeServerGroup(target_cldbid, group); + applied_groups.push_back(group); + } else { + group_manager->enableCache(target_cldbid); + scope_exit_callback cache_disable{[group_manager, target_cldbid]{ + group_manager->disableCache(target_cldbid); + }}; - for(const auto& _server : server ? std::deque>{server} : serverInstance->getVoiceServerManager()->serverInstances()) { - for (const auto &targetClient : _server->findClientsByCldbId(target_cldbid)) { - if (_server->notifyClientPropertyUpdates(targetClient, _server->groups->update_server_group_property(targetClient, true))) { - for (const auto &client : _server->getClients()) { - if (client->isClientVisible(targetClient, true) || client == targetClient) - client->notifyServerGroupClientRemove(_this.lock(), targetClient, serverGroup); - } - if(targetClient->update_cached_permissions()) /* update cached calculated permissions */ - targetClient->sendNeededPermissions(false); /* cached permissions had changed, notify the client */ - targetClient->updateChannelClientProperties(true, true); - } - } - } + for(const auto& group : target_groups) { + auto assignment = group_manager->get_group_assignment(target_cldbid, group); + if(!assignment) { + if(continue_on_error) + continue; + return {findError("parameter_invalid"), "Client is not member of server group " + to_string(group->groupId())}; + } + if(assignment->server != (target_server ? target_server->getServerId() : 0)) { + if(continue_on_error) + continue; + return {findError("parameter_invalid"), "Group assignment for group " + to_string(assignment->group->groupId()) + " hasn't been made over the target server. Assignment origin server id " + to_string(assignment->server)}; + } - return CommandResult::Success; + applied_groups.push_back(group); + group_manager->removeServerGroup(target_cldbid, group); + } + } + + for(const auto& _server : target_server ? std::deque>{target_server} : serverInstance->getVoiceServerManager()->serverInstances()) { + for (const auto &targetClient : _server->findClientsByCldbId(target_cldbid)) { + if (_server->notifyClientPropertyUpdates(targetClient, _server->groups->update_server_group_property(targetClient, true))) { + for (const auto &client : _server->getClients()) { + if(client->isClientVisible(targetClient, true) || client == targetClient) + for(const auto& group : applied_groups) + client->notifyServerGroupClientRemove(_this.lock(), targetClient, group); + } + if(targetClient->update_cached_permissions()) /* update cached calculated permissions */ + targetClient->sendNeededPermissions(false); /* cached permissions had changed, notify the client */ + targetClient->updateChannelClientProperties(true, true); + } + } + } + + return CommandResult::Success; } CommandResult ConnectedClient::handleCommandServerGroupPermList(Command &cmd) { diff --git a/server/src/client/SpeakingClient.cpp b/server/src/client/SpeakingClient.cpp index 9fafaf8..e6a0363 100644 --- a/server/src/client/SpeakingClient.cpp +++ b/server/src/client/SpeakingClient.cpp @@ -347,7 +347,7 @@ CommandResult SpeakingClient::handleCommandClientInit(Command& cmd) { TIMING_START(timings); if(!DatabaseHelper::assignDatabaseId(this->server->getSql(), this->server->getServerId(), _this.lock())) return {findError("vs_critical"), "Could not assign database id!"}; TIMING_STEP(timings, "db assign "); - this->server->getGroupManager()->enableCache(_this.lock()); + this->server->getGroupManager()->enableCache(this->getClientDatabaseId()); TIMING_STEP(timings, "gr cache "); const static vector available_parameters = { @@ -716,7 +716,7 @@ void SpeakingClient::processLeave() { unique_lock server_channel_lock(this->server->channel_tree_lock); server->unregisterClient(ownLock, "disconnected", server_channel_lock); /* already moves client to void if needed */ } - server->groups->disableCache(ownLock); + server->groups->disableCache(ownLock->getClientDatabaseId()); server->musicManager->cleanup_client_bots(this->getClientDatabaseId()); //ref_server = nullptr; Removed caused nullptr exceptions } diff --git a/server/src/client/query/QueryClient.cpp b/server/src/client/query/QueryClient.cpp index 8e1a063..e24e623 100644 --- a/server/src/client/query/QueryClient.cpp +++ b/server/src/client/query/QueryClient.cpp @@ -159,7 +159,7 @@ bool QueryClient::closeConnection(const std::chrono::system_clock::time_point& f unique_lock channel_lock(this->server->channel_tree_lock); this->server->unregisterClient(_this.lock(), "disconnected", channel_lock); } - this->server->groups->disableCache(_this.lock()); + this->server->groups->disableCache(this->getClientDatabaseId()); this->server = nullptr; } @@ -234,7 +234,7 @@ void QueryClient::disconnectFinal() { unique_lock channel_lock(this->server->channel_tree_lock); this->server->unregisterClient(_this.lock(), "disconnected", channel_lock); } - this->server->groups->disableCache(_this.lock()); + this->server->groups->disableCache(this->getClientDatabaseId()); this->server = nullptr; } diff --git a/server/src/client/query/QueryClientCommands.cpp b/server/src/client/query/QueryClientCommands.cpp index 7481b2e..bd54fa6 100644 --- a/server/src/client/query/QueryClientCommands.cpp +++ b/server/src/client/query/QueryClientCommands.cpp @@ -177,8 +177,8 @@ CommandResult QueryClient::handleCommandLogin(Command& cmd) { this->server->client_move(this->ref(), nullptr, nullptr, "", ViewReasonId::VREASON_USER_ACTION, false, tree_lock); this->server->unregisterClient(_this.lock(), "login", tree_lock); } - this->server->groups->disableCache(_this.lock()); - } else serverInstance->getGroupManager()->disableCache(_this.lock()); + this->server->groups->disableCache(this->getClientDatabaseId()); + } else serverInstance->getGroupManager()->disableCache(this->getClientDatabaseId()); logMessage(LOG_QUERY, "Got new authenticated client. Username: {}, Unique-ID: {}, Bounded Server: {}", account->username, account->unique_id, account->bound_server); @@ -198,7 +198,7 @@ CommandResult QueryClient::handleCommandLogin(Command& cmd) { DatabaseHelper::assignDatabaseId(this->sql, static_cast(target_server ? target_server->getServerId() : 0), _this.lock()); if(target_server) { - target_server->groups->enableCache(_this.lock()); + target_server->groups->enableCache(this->getClientDatabaseId()); target_server->registerClient(_this.lock()); { @@ -221,7 +221,7 @@ CommandResult QueryClient::handleCommandLogin(Command& cmd) { else this->update_cached_permissions(); } else { - serverInstance->getGroupManager()->enableCache(_this.lock()); + serverInstance->getGroupManager()->enableCache(this->getClientDatabaseId()); this->update_cached_permissions(); } @@ -245,15 +245,15 @@ CommandResult QueryClient::handleCommandLogout(Command &) { this->server->client_move(this->ref(), nullptr, nullptr, "", ViewReasonId::VREASON_USER_ACTION, false, tree_lock); this->server->unregisterClient(_this.lock(), "logout", tree_lock); } - this->server->groups->disableCache(_this.lock()); - } else serverInstance->getGroupManager()->disableCache(_this.lock()); + this->server->groups->disableCache(this->getClientDatabaseId()); + } else serverInstance->getGroupManager()->disableCache(this->getClientDatabaseId()); this->properties()[property::CLIENT_UNIQUE_IDENTIFIER] = "UnknownQuery"; //TODO load from table this->properties()[property::CLIENT_NICKNAME] = string() + "ServerQuery#" + this->getLoggingPeerIp() + "/" + to_string(ntohs(this->getPeerPort())); DatabaseHelper::assignDatabaseId(this->sql, static_cast(this->server ? this->server->getServerId() : 0), _this.lock()); if(this->server){ - this->server->groups->enableCache(_this.lock()); + this->server->groups->enableCache(this->getClientDatabaseId()); this->server->registerClient(this->ref()); { @@ -274,7 +274,7 @@ CommandResult QueryClient::handleCommandLogout(Command &) { this->update_cached_permissions(); } } else { - serverInstance->getGroupManager()->enableCache(_this.lock()); + serverInstance->getGroupManager()->enableCache(this->getClientDatabaseId()); this->update_cached_permissions(); } @@ -322,10 +322,10 @@ CommandResult QueryClient::handleCommandServerSelect(Command &cmd) { this->server->client_move(this->ref(), nullptr, nullptr, "", ViewReasonId::VREASON_USER_ACTION, false, tree_lock); this->server->unregisterClient(_this.lock(), "server switch", tree_lock); } - server_locked->groups->disableCache(_this.lock()); + server_locked->groups->disableCache(this->getClientDatabaseId()); this->channels->reset(); } else - serverInstance->getGroupManager()->disableCache(_this.lock()); + serverInstance->getGroupManager()->disableCache(this->getClientDatabaseId()); } this->resetEventMask(); @@ -341,7 +341,7 @@ CommandResult QueryClient::handleCommandServerSelect(Command &cmd) { DatabaseHelper::assignDatabaseId(this->sql, static_cast(this->server ? this->server->getServerId() : 0), _this.lock()); if(this->server) { - this->server->groups->enableCache(_this.lock()); + this->server->groups->enableCache(this->getClientDatabaseId()); this->server->registerClient(_this.lock()); { @@ -359,7 +359,7 @@ CommandResult QueryClient::handleCommandServerSelect(Command &cmd) { else this->update_cached_permissions(); } else { - serverInstance->getGroupManager()->enableCache(_this.lock()); + serverInstance->getGroupManager()->enableCache(this->getClientDatabaseId()); this->update_cached_permissions(); } this->updateChannelClientProperties(true, true); diff --git a/server/src/client/web/WebClient.cpp b/server/src/client/web/WebClient.cpp index a26292e..566dd06 100644 --- a/server/src/client/web/WebClient.cpp +++ b/server/src/client/web/WebClient.cpp @@ -181,7 +181,7 @@ bool WebClient::closeConnection(const std::chrono::system_clock::time_point& tim unique_lock server_channel_lock(this->server->channel_tree_lock); this->server->unregisterClient(_this.lock(), "disconnected", server_channel_lock); } - this->server->groups->disableCache(_this.lock()); + this->server->groups->disableCache(this->getClientDatabaseId()); //this->server = nullptr; } diff --git a/server/src/music/MusicBotManager.cpp b/server/src/music/MusicBotManager.cpp index ecb28ce..dc5fd32 100644 --- a/server/src/music/MusicBotManager.cpp +++ b/server/src/music/MusicBotManager.cpp @@ -83,7 +83,7 @@ std::shared_ptr MusicBotManager::createBot(ClientDbId owner (LOG_SQL_CMD)(sql::command(handle->getSql(), "INSERT INTO `musicbots` (`serverId`, `botId`, `uniqueId`, `owner`) VALUES (:sid, :botId, :uid, :owner)", variable{":sid", handle->getServerId()}, variable{":botId", musicBot->getClientDatabaseId()}, variable{":uid", musicBot->getUid()}, variable{":owner", owner}).execute()); musicBot->properties()[property::CLIENT_OWNER] = owner; - handle->groups->enableCache(musicBot); + handle->groups->enableCache(musicBot->getClientDatabaseId()); musicBot->setDisplayName("Im a music bot!"); musicBot->properties()[property::CLIENT_LASTCONNECTED] = duration_cast(system_clock::now().time_since_epoch()).count(); musicBot->properties()[property::CLIENT_CREATED] = duration_cast(system_clock::now().time_since_epoch()).count(); @@ -139,7 +139,7 @@ void MusicBotManager::deleteBot(std::shared_ptr musicBot) { handle->client_move(musicBot, nullptr, nullptr, "Music bot deleted", ViewReasonId::VREASON_SERVER_LEFT, true, server_channel_lock); handle->unregisterClient(musicBot, "bot deleted", server_channel_lock); } - handle->groups->disableCache(musicBot); + handle->groups->disableCache(musicBot->getClientDatabaseId()); serverInstance->databaseHelper()->deleteClient(handle, musicBot->getClientDatabaseId()); serverInstance->databaseHelper()->deleteClient(nullptr, musicBot->getClientDatabaseId()); @@ -233,7 +233,7 @@ int MusicBotManager::sqlCreateMusicBot(int length, std::string* values, std::str musicBot->properties()[property::CLIENT_LASTCONNECTED] = duration_cast(system_clock::now().time_since_epoch()).count(); } - handle->groups->enableCache(musicBot); + handle->groups->enableCache(musicBot->getClientDatabaseId()); if(musicBot->getClientDatabaseId() != botId) logCritical("Invalid music bot id mapping!"); { diff --git a/server/src/server/QueryServer.cpp b/server/src/server/QueryServer.cpp index c29831a..9249f03 100644 --- a/server/src/server/QueryServer.cpp +++ b/server/src/server/QueryServer.cpp @@ -45,9 +45,9 @@ void QueryServer::unregisterConnection(const shared_ptr &client) { } if(client->server) { - client->server->getGroupManager()->disableCache(client); + client->server->getGroupManager()->disableCache(client->getClientDatabaseId()); } else { - serverInstance->getGroupManager()->disableCache(client); + serverInstance->getGroupManager()->disableCache(client->getClientDatabaseId()); } /* client->handle = nullptr; */ } diff --git a/shared b/shared index a086dcc..4a9d8f1 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit a086dcc214fe4ea7a983fecebb93b8e2fe3258ff +Subproject commit 4a9d8f132fe9ca3411e2e3c245922ad778c56aa0