Added two new commands
This commit is contained in:
@@ -30,6 +30,7 @@
|
||||
#include <misc/digest.h>
|
||||
#include <misc/rnd.h>
|
||||
#include <misc/timer.h>
|
||||
#include <misc/scope_guard.h>
|
||||
#include <bbcode/bbcodes.h>
|
||||
|
||||
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<GroupId>());
|
||||
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<ClientDbId>();
|
||||
{
|
||||
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<std::shared_ptr<Group>> target_groups;
|
||||
vector<std::shared_ptr<Group>> 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<GroupId>() && continue_on_error)
|
||||
continue;
|
||||
|
||||
auto gid = group_id.as<GroupId>();
|
||||
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<shared_ptr<TSServer>>{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<shared_ptr<TSServer>>{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<GroupId>());
|
||||
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<ClientDbId>();
|
||||
{
|
||||
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<std::shared_ptr<Group>> target_groups;
|
||||
vector<std::shared_ptr<Group>> 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<GroupId>() && continue_on_error)
|
||||
continue;
|
||||
|
||||
auto gid = group_id.as<GroupId>();
|
||||
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<shared_ptr<TSServer>>{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<shared_ptr<TSServer>>{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) {
|
||||
|
||||
Reference in New Issue
Block a user