From 1865a3b20ddaac54cfa180588ce8ba1a623ef278 Mon Sep 17 00:00:00 2001 From: WolverinDEV Date: Thu, 2 Apr 2020 14:10:33 +0200 Subject: [PATCH] Fixed the permfind command --- git-teaspeak | 2 +- server/src/client/command_handler/misc.cpp | 144 +++++++++++++++------ shared | 2 +- 3 files changed, 104 insertions(+), 44 deletions(-) diff --git a/git-teaspeak b/git-teaspeak index 3b5787d..59e5721 160000 --- a/git-teaspeak +++ b/git-teaspeak @@ -1 +1 @@ -Subproject commit 3b5787d4d98dab2bfa732c906710f149a7f93395 +Subproject commit 59e57218969572d50fd9f014ab5df59046b7a196 diff --git a/server/src/client/command_handler/misc.cpp b/server/src/client/command_handler/misc.cpp index a14cd09..354f9a1 100644 --- a/server/src/client/command_handler/misc.cpp +++ b/server/src/client/command_handler/misc.cpp @@ -1329,7 +1329,9 @@ command_result ConnectedClient::handleCommandPermFind(Command &cmd) { CMD_CHK_AND_INC_FLOOD_POINTS(5); ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_permission_find, 1); - deque, bool>> permissions; + std::vector> requested_permissions{}; + requested_permissions.reserve(cmd.bulkCount()); + std::shared_ptr permission; for(size_t index = 0; index < cmd.bulkCount(); index++) { bool granted = false; @@ -1349,22 +1351,21 @@ command_result ConnectedClient::handleCommandPermFind(Command &cmd) { continue; } - permissions.emplace_back(pair, bool>{{permission->name, permission->type}, granted}); + requested_permissions.emplace_back(permission->name, permission->type, granted); } - if(permissions.empty()) + if(requested_permissions.empty()) return command_result{error::database_empty_result}; - map flags; - map quick_mapping; - string query_string; - for(const auto& entry : permissions) { - if(flags[entry.first.first] == 0) { - quick_mapping[entry.first.first] = entry.first.second; - query_string += string(query_string.empty() ? "" : " OR ") + "`permId` = '" + entry.first.first + "'"; + std::map> db_lookup_mapping{}; + std::string query_string{}; + for(const auto& [name, id, as_granted] : requested_permissions) { + auto& mapping = db_lookup_mapping[name]; + if(std::get<0>(mapping) == 0) { + std::get<0>(mapping) = id; + query_string += std::string{query_string.empty() ? "" : " OR "} + "`permId` = '" + name + "'"; } - - flags[entry.first.first] |= entry.second ? 2 : 1; + std::get<1>(mapping) |= (1U << as_granted); } deque> entries; @@ -1373,13 +1374,14 @@ command_result ConnectedClient::handleCommandPermFind(Command &cmd) { variable{":sid", this->server->getServerId()}, variable{":playlist", permission::SQL_PERM_PLAYLIST} ).query([&](int length, string* values, string* columns) { - permission::PermissionSqlType type = permission::SQL_PERM_GROUP; - uint64_t id = 0; - ChannelId channel_id = 0; - permission::PermissionValue value = 0, - granted_value = 0; - string permission_name; + permission::PermissionSqlType type{permission::SQL_PERM_GROUP}; + uint64_t id{0}; + ChannelId channel_id{0}; + permission::PermissionValue value{0}, granted_value{0}; + string permission_name{}; bool negate = false, skip = false; + +#if 0 for (int index = 0; index < length; index++) { try { if(columns[index] == "type") @@ -1403,35 +1405,48 @@ command_result ConnectedClient::handleCommandPermFind(Command &cmd) { return 0; } } +#else + assert(length == 8); + try { + type = static_cast(stoll(values[1])); + permission_name = values[0]; + id = static_cast(stoll(values[2])); + channel_id = static_cast(stoll(values[3])); + value = static_cast(stoll(values[4])); + granted_value = static_cast(stoll(values[5])); + negate = values[7] == "1"; + skip = values[6] == "1"; + } catch(std::exception& ex) { + return 0; + } +#endif + auto request = db_lookup_mapping.find(permission_name); + if(request == db_lookup_mapping.end()) return 0; /* shall not happen */ + + auto flags = std::get<1>(request->second); /* value */ - if((flags[permission_name] & 0x1) > 0 && value > 0) { + if((flags & 0x1U) > 0 && value > 0) { auto result = make_unique(); - result->permission_type = quick_mapping[permission_name]; + result->permission_type = std::get<0>(request->second); result->permission_value = value; result->type = type; result->channel_id = channel_id; result->negate = negate; result->skip = skip; if (type == permission::SQL_PERM_GROUP) { - auto gr = this->server->groups->findGroup(id); - if (!gr) return 0; - result->group_id = id; - if(gr->target() == GROUPTARGET_CHANNEL) - result->channel_id = 1; } else if(type == permission::SQL_PERM_USER) { result->client_id = id; } - if(result) - entries.push_back(std::move(result)); + entries.push_back(std::move(result)); } /* granted */ - if((flags[permission_name] & 0x2) > 0 && granted_value > 0) { + if((flags & 0x2U) > 0 && granted_value > 0) { auto result = make_unique(); - result->permission_type = (permission::PermissionType) (quick_mapping[permission_name] | PERM_ID_GRANT); + result->permission_type = (permission::PermissionType) (std::get<0>(request->second) | PERM_ID_GRANT); result->permission_value = granted_value; result->type = type; result->channel_id = channel_id; @@ -1439,21 +1454,17 @@ command_result ConnectedClient::handleCommandPermFind(Command &cmd) { result->skip = skip; if (type == permission::SQL_PERM_GROUP) { - auto gr = this->server->groups->findGroup(id); - if (!gr) return 0; - result->group_id = id; - if(gr->target() == GROUPTARGET_CHANNEL) - result->channel_id = 1; } else if(type == permission::SQL_PERM_USER) { result->client_id = id; } - if(result) - entries.push_back(std::move(result)); + entries.push_back(std::move(result)); } return 0; }); + if(entries.empty()) + return command_result{error::database_empty_result}; struct CommandPerm { permission::PermissionType p; @@ -1465,13 +1476,13 @@ command_result ConnectedClient::handleCommandPermFind(Command &cmd) { std::vector perms; perms.resize(entries.size()); - size_t index = 0; + + size_t index{0}; + auto all_groups = this->server->groups->availableGroups(true); for(const auto& entry : entries) { auto& perm = perms[index++]; - perm.p = entry->permission_type; - perm.v = entry->permission_value; - +#if 0 /* TS3 switched the oder and YatQa as well, to keep compatibility we do it as well */ if(entry->type == permission::SQL_PERM_USER) { if(entry->channel_id > 0) { perm.id1 = entry->client_id; @@ -1497,7 +1508,42 @@ command_result ConnectedClient::handleCommandPermFind(Command &cmd) { perm.t = 0; /* server group */ } } +#else + if(entry->type == permission::SQL_PERM_USER) { + if(entry->channel_id > 0) { + perm.id1 = entry->channel_id; + perm.id2 = entry->client_id; + perm.t = 4; /* client channel */ + } else { + perm.id1 = entry->client_id; + perm.id2 = 0; + perm.t = 1; /* client server */ + } + } else if(entry->type == permission::SQL_PERM_CHANNEL) { + perm.id1 = entry->channel_id; + perm.id2 = 0; + perm.t = 2; /* channel permission */ + } else if(entry->type == permission::SQL_PERM_GROUP) { + auto group = std::find_if(all_groups.begin(), all_groups.end(), [&](const auto& group) { return group->groupId() == entry->group_id; }); + if(group == all_groups.end()) { + index--; /* unknown group */ + continue; + } + if((*group)->target() == GroupTarget::GROUPTARGET_CHANNEL) { + perm.id1 = 0; + perm.id2 = entry->group_id; + perm.t = 3; /* channel group */ + } else { + perm.id1 = entry->group_id; + perm.id2 = 0; + perm.t = 0; /* server group */ + } + } +#endif + perm.p = entry->permission_type; + perm.v = entry->permission_value; } + perms.erase(perms.begin() + index, perms.end()); sort(perms.begin(), perms.end(), [](const CommandPerm& a, const CommandPerm& b) { @@ -1516,6 +1562,7 @@ command_result ConnectedClient::handleCommandPermFind(Command &cmd) { return &a > &b; }); +#if 0 Command result(this->notify_response_command("notifypermfind")); index = 0; @@ -1528,9 +1575,22 @@ command_result ConnectedClient::handleCommandPermFind(Command &cmd) { result[index]["t"] = e.t; index++; } - - if(index == 0) return command_result{error::database_empty_result}; this->sendCommand(result); +#else + command_builder result{this->notify_response_command("notifypermfind"), 64, perms.size()}; + index = 0; + + for(const auto& e : perms) { + auto bulk = result.bulk(index++); + bulk.put("t", e.t); + bulk.put("p", (uint16_t) e.p); + bulk.put("v", e.v); + bulk.put("id1", e.id1); + bulk.put("id2", e.id2); + } + this->sendCommand(result); +#endif + return command_result{error::ok}; } diff --git a/shared b/shared index 889477c..c879f3b 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit 889477c6461164cb1dd687b270bd629763db1ef6 +Subproject commit c879f3b7764e2b6a226ca80d3013bdff838a9972