Added the action logging system
This commit is contained in:
@@ -6,10 +6,12 @@
|
||||
#include <PermissionManager.h>
|
||||
#include <src/client/ConnectedClient.h>
|
||||
#include "./helpers.h"
|
||||
#include "../../manager/ActionLogger.h"
|
||||
|
||||
namespace ts::command::bulk_parser {
|
||||
template <bool kParseValue>
|
||||
class PermissionBulkParser {
|
||||
friend class PermissionBulkParser<false>;
|
||||
public:
|
||||
explicit PermissionBulkParser(ts::ParameterBulk& bulk) {
|
||||
if(bulk.has("permid")) {
|
||||
@@ -45,7 +47,7 @@ namespace ts::command::bulk_parser {
|
||||
}
|
||||
}
|
||||
PermissionBulkParser(const PermissionBulkParser&) = delete;
|
||||
PermissionBulkParser(PermissionBulkParser&&) = default;
|
||||
PermissionBulkParser(PermissionBulkParser&&) noexcept = default;
|
||||
|
||||
~PermissionBulkParser() {
|
||||
this->error_.release_data();
|
||||
@@ -78,9 +80,9 @@ namespace ts::command::bulk_parser {
|
||||
|
||||
inline void apply_to(const std::shared_ptr<permission::v2::PermissionManager>& manager, permission::v2::PermissionUpdateType mode) const {
|
||||
if(this->is_grant_permission()) {
|
||||
manager->set_permission(this->permission_type(), { 0, this->value() }, permission::v2::PermissionUpdateType::do_nothing, mode);
|
||||
this->old_value = manager->set_permission(this->permission_type(), { 0, this->value() }, permission::v2::PermissionUpdateType::do_nothing, mode);
|
||||
} else {
|
||||
manager->set_permission(
|
||||
this->old_value = manager->set_permission(
|
||||
this->permission_type(),
|
||||
{ this->value(), 0 },
|
||||
mode,
|
||||
@@ -91,11 +93,61 @@ namespace ts::command::bulk_parser {
|
||||
}
|
||||
}
|
||||
|
||||
inline void log_update(
|
||||
server::log::PermissionActionLogger& logger,
|
||||
ServerId sid,
|
||||
const std::shared_ptr<server::ConnectedClient>& issuer,
|
||||
server::log::PermissionTarget target,
|
||||
permission::v2::PermissionUpdateType mode,
|
||||
uint64_t id1, const std::string& id1_name,
|
||||
uint64_t id2, const std::string& id2_name
|
||||
) const {
|
||||
if(this->is_grant_permission()) {
|
||||
switch (mode) {
|
||||
case permission::v2::delete_value:
|
||||
if(!this->old_value.flags.grant_set)
|
||||
return;
|
||||
|
||||
logger.log_permission_remove_grant(sid, issuer, target, id1, id1_name, id2, id2_name, *this->permission_, this->old_value.values.grant);
|
||||
break;
|
||||
|
||||
case permission::v2::set_value:
|
||||
if(this->old_value.flags.grant_set) {
|
||||
logger.log_permission_edit_grant(sid, issuer, target, id1, id1_name, id2, id2_name, *this->permission_, this->old_value.values.grant, this->value_);
|
||||
} else {
|
||||
logger.log_permission_add_grant(sid, issuer, target, id1, id1_name, id2, id2_name, *this->permission_, this->value_);
|
||||
}
|
||||
break;
|
||||
case permission::v2::do_nothing:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (mode) {
|
||||
case permission::v2::delete_value:
|
||||
if(!this->old_value.flags.value_set)
|
||||
return;
|
||||
|
||||
logger.log_permission_remove_value(sid, issuer, target, id1, id1_name, id2, id2_name, *this->permission_, this->old_value.values.value, this->old_value.flags.negate, this->old_value.flags.skip);
|
||||
break;
|
||||
|
||||
case permission::v2::set_value:
|
||||
if(this->old_value.flags.value_set) {
|
||||
logger.log_permission_edit_value(sid, issuer, target, id1, id1_name, id2, id2_name, *this->permission_, this->old_value.values.value, this->old_value.flags.negate, this->old_value.flags.skip, this->value_, this->flag_negated_, this->flag_skip_);
|
||||
} else {
|
||||
logger.log_permission_add_value(sid, issuer, target, id1, id1_name, id2, id2_name, *this->permission_, this->old_value.values.value, this->old_value.flags.negate, this->old_value.flags.skip);
|
||||
}
|
||||
break;
|
||||
case permission::v2::do_nothing:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void apply_to_channel(const std::shared_ptr<permission::v2::PermissionManager>& manager, permission::v2::PermissionUpdateType mode, ChannelId channel_id) const {
|
||||
if(this->is_grant_permission()) {
|
||||
manager->set_channel_permission(this->permission_type(), channel_id, { this->value(), true }, permission::v2::PermissionUpdateType::do_nothing, mode);
|
||||
this->old_value = manager->set_channel_permission(this->permission_type(), channel_id, { this->value(), true }, permission::v2::PermissionUpdateType::do_nothing, mode);
|
||||
} else {
|
||||
manager->set_channel_permission(
|
||||
this->old_value = manager->set_channel_permission(
|
||||
this->permission_type(),
|
||||
channel_id,
|
||||
{ this->value(), true },
|
||||
@@ -122,6 +174,7 @@ namespace ts::command::bulk_parser {
|
||||
permission::PermissionValue value_{0};
|
||||
ts::command_result error_{error::ok};
|
||||
|
||||
mutable permission::v2::PermissionContainer old_value{};
|
||||
#ifndef NDEBUG
|
||||
bool error_released_{false};
|
||||
#endif
|
||||
@@ -131,7 +184,7 @@ namespace ts::command::bulk_parser {
|
||||
class PermissionBulksParser {
|
||||
public:
|
||||
PermissionBulksParser(const PermissionBulksParser&) = delete;
|
||||
PermissionBulksParser(PermissionBulksParser&&) = default;
|
||||
PermissionBulksParser(PermissionBulksParser&&) noexcept = default;
|
||||
|
||||
template <typename base_iterator>
|
||||
struct FilteredPermissionIterator : public base_iterator {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "../../weblist/WebListManager.h"
|
||||
#include "../../manager/ConversationManager.h"
|
||||
#include "../../manager/PermissionNameMapper.h"
|
||||
#include "../../manager/ActionLogger.h"
|
||||
#include <cstdint>
|
||||
|
||||
#include "helpers.h"
|
||||
@@ -138,11 +139,30 @@ command_result ConnectedClient::handleCommandChannelGroupAdd(Command &cmd) {
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_channelgroup_create, 1);
|
||||
|
||||
auto group_manager = this->server ? this->server->getGroupManager() : serverInstance->getGroupManager().get();
|
||||
if(cmd["type"].as<GroupType>() == GroupType::GROUP_TYPE_NORMAL && !this->server) return command_result{error::parameter_invalid, "You cant create normal channel groups on the template server"};
|
||||
if(cmd["name"].string().empty()) return command_result{error::parameter_invalid, "invalid group name"};
|
||||
|
||||
log::GroupType log_group_type;
|
||||
if(cmd["type"].as<GroupType>() == GroupType::GROUP_TYPE_QUERY) {
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_serverinstance_modify_querygroup, 1);
|
||||
log_group_type = log::GroupType::QUERY;
|
||||
} else if(cmd["type"].as<GroupType>() == GroupType::GROUP_TYPE_TEMPLATE) {
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_serverinstance_modify_templates, 1);
|
||||
log_group_type = log::GroupType::TEMPLATE;
|
||||
} else {
|
||||
if(!this->server)
|
||||
return command_result{error::parameter_invalid, "you cant create normal groups on the template server!"};
|
||||
log_group_type = log::GroupType::NORMAL;
|
||||
}
|
||||
|
||||
if(cmd["name"].string().empty())
|
||||
return command_result{error::parameter_invalid, "invalid group name"};
|
||||
|
||||
for(const auto& gr : group_manager->availableServerGroups(true))
|
||||
if(gr->name() == cmd["name"].string() && gr->target() == GroupTarget::GROUPTARGET_CHANNEL) return command_result{error::parameter_invalid, "Group already exists"};
|
||||
if(gr->name() == cmd["name"].string() && gr->target() == GroupTarget::GROUPTARGET_CHANNEL)
|
||||
return command_result{error::parameter_invalid, "Group already exists"};
|
||||
|
||||
auto group = group_manager->createGroup(GroupTarget::GROUPTARGET_CHANNEL, cmd["type"].as<GroupType>(), cmd["name"].string());
|
||||
serverInstance->action_logger()->group_logger.log_group_create(this->getServerId(), this->ref(), log::GroupTarget::CHANNEL, log_group_type, group->groupId(), group->name(), 0, "");
|
||||
|
||||
if (group) {
|
||||
group->permissions()->set_permission(permission::b_group_is_permanent, {1, 0}, permission::v2::set_value, permission::v2::do_nothing);
|
||||
if(this->server)
|
||||
@@ -212,6 +232,28 @@ command_result ConnectedClient::handleCommandChannelGroupCopy(Command &cmd) {
|
||||
if(!group_manager->copyGroupPermissions(source_group, target_group))
|
||||
return command_result{error::vs_critical, "failed to copy group permissions"};
|
||||
|
||||
log::GroupType log_group_type;
|
||||
switch (target_group->type()) {
|
||||
case GroupType::GROUP_TYPE_QUERY:
|
||||
log_group_type = log::GroupType::QUERY;
|
||||
break;
|
||||
|
||||
case GroupType::GROUP_TYPE_TEMPLATE:
|
||||
log_group_type = log::GroupType::TEMPLATE;
|
||||
break;
|
||||
|
||||
case GroupType::GROUP_TYPE_NORMAL:
|
||||
log_group_type = log::GroupType::NORMAL;
|
||||
break;
|
||||
|
||||
default:
|
||||
return command_result{error::parameter_invalid, "type"};
|
||||
}
|
||||
|
||||
serverInstance->action_logger()->group_logger.log_group_permission_copy(target_group->type() != GroupType::GROUP_TYPE_NORMAL ? 0 : this->getServerId(),
|
||||
this->ref(), log::GroupTarget::CHANNEL, log_group_type, target_group->groupId(), target_group->name(), source_group->groupId(), source_group->name());
|
||||
|
||||
|
||||
global_update = !this->server || !group_manager->isLocalGroup(target_group);
|
||||
} else {
|
||||
//Copy a new group
|
||||
@@ -223,6 +265,24 @@ command_result ConnectedClient::handleCommandChannelGroupCopy(Command &cmd) {
|
||||
return command_result{result};
|
||||
}
|
||||
|
||||
log::GroupType log_group_type;
|
||||
switch (target_type) {
|
||||
case GroupType::GROUP_TYPE_QUERY:
|
||||
log_group_type = log::GroupType::QUERY;
|
||||
break;
|
||||
|
||||
case GroupType::GROUP_TYPE_TEMPLATE:
|
||||
log_group_type = log::GroupType::TEMPLATE;
|
||||
break;
|
||||
|
||||
case GroupType::GROUP_TYPE_NORMAL:
|
||||
log_group_type = log::GroupType::NORMAL;
|
||||
break;
|
||||
|
||||
default:
|
||||
return command_result{error::parameter_invalid, "type"};
|
||||
}
|
||||
|
||||
if(!ref_server && target_type == GroupType::GROUP_TYPE_NORMAL)
|
||||
return command_result{error::parameter_invalid, "You cant create normal groups on the template server!"};
|
||||
|
||||
@@ -232,6 +292,8 @@ command_result ConnectedClient::handleCommandChannelGroupCopy(Command &cmd) {
|
||||
auto target_group_id = group_manager->copyGroup(source_group, target_type, cmd["name"], target_type != GroupType::GROUP_TYPE_NORMAL ? 0 : this->getServerId());
|
||||
if(target_group_id == 0)
|
||||
return command_result{error::vs_critical, "failed to copy group"};
|
||||
serverInstance->action_logger()->group_logger.log_group_create(target_type != GroupType::GROUP_TYPE_NORMAL ? 0 : this->getServerId(),
|
||||
this->ref(), log::GroupTarget::CHANNEL, log_group_type, target_group_id, cmd["name"], source_group->groupId(), source_group->name());
|
||||
|
||||
if(this->getType() == ClientType::CLIENT_QUERY) {
|
||||
Command notify("");
|
||||
@@ -256,10 +318,26 @@ command_result ConnectedClient::handleCommandChannelGroupRename(Command &cmd) {
|
||||
|
||||
auto group_manager = this->server ? this->server->getGroupManager() : serverInstance->getGroupManager().get();
|
||||
auto channel_group = group_manager->findGroup(cmd["cgid"].as<GroupId>());
|
||||
if (!channel_group || channel_group->target() != GROUPTARGET_CHANNEL) return command_result{error::parameter_invalid, "invalid channel group id"};
|
||||
if (!channel_group || channel_group->target() != GROUPTARGET_CHANNEL)
|
||||
return command_result{error::parameter_invalid, "invalid channel group id"};
|
||||
ACTION_REQUIRES_GROUP_PERMISSION(channel_group, permission::i_channel_group_needed_modify_power, permission::i_channel_group_modify_power, true);
|
||||
|
||||
auto type = channel_group->type();
|
||||
log::GroupType log_group_type;
|
||||
if(type == GroupType::GROUP_TYPE_QUERY) {
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_serverinstance_modify_querygroup, 1);
|
||||
log_group_type = log::GroupType::QUERY;
|
||||
} else if(type == GroupType::GROUP_TYPE_TEMPLATE) {
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_serverinstance_modify_templates, 1);
|
||||
log_group_type = log::GroupType::TEMPLATE;
|
||||
} else {
|
||||
log_group_type = log::GroupType::NORMAL;
|
||||
}
|
||||
|
||||
auto old_name = channel_group->name();
|
||||
group_manager->renameGroup(channel_group, cmd["name"].string());
|
||||
serverInstance->action_logger()->group_logger.log_group_rename(this->getServerId(), this->ref(), log::GroupTarget::CHANNEL, log_group_type, channel_group->groupId(), channel_group->name(), old_name);
|
||||
|
||||
if(this->server)
|
||||
this->server->forEachClient([](shared_ptr<ConnectedClient> cl) {
|
||||
cl->notifyChannelGroupList();
|
||||
@@ -285,21 +363,37 @@ command_result ConnectedClient::handleCommandChannelGroupDel(Command &cmd) {
|
||||
}
|
||||
if(serverInstance->properties()[property::SERVERINSTANCE_TEMPLATE_CHANNELDEFAULT_GROUP] == channel_group->groupId())
|
||||
return command_result{error::parameter_invalid, "Could not delete instance default channel group!"};
|
||||
|
||||
if(serverInstance->properties()[property::SERVERINSTANCE_TEMPLATE_CHANNELADMIN_GROUP] == channel_group->groupId())
|
||||
return command_result{error::parameter_invalid, "Could not delete instance default channel admin group!"};
|
||||
|
||||
auto type = channel_group->type();
|
||||
log::GroupType log_group_type;
|
||||
if(type == GroupType::GROUP_TYPE_QUERY) {
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_serverinstance_modify_querygroup, 1);
|
||||
log_group_type = log::GroupType::QUERY;
|
||||
} else if(type == GroupType::GROUP_TYPE_TEMPLATE) {
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_serverinstance_modify_templates, 1);
|
||||
log_group_type = log::GroupType::TEMPLATE;
|
||||
} else {
|
||||
log_group_type = log::GroupType::NORMAL;
|
||||
}
|
||||
|
||||
if (!cmd["force"].as<bool>())
|
||||
if (!group_manager->listGroupMembers(channel_group, false).empty())
|
||||
return command_result{error::database_empty_result, "group not empty!"};
|
||||
|
||||
if (group_manager->deleteGroup(channel_group) && this->server) {
|
||||
this->server->forEachClient([&](shared_ptr<ConnectedClient> cl) {
|
||||
if(this->server->notifyClientPropertyUpdates(cl, this->server->groups->update_server_group_property(cl, true, cl->getChannel()))) {
|
||||
if(cl->update_cached_permissions()) /* update cached calculated permissions */
|
||||
cl->sendNeededPermissions(false); /* cached permissions had changed, notify the client */
|
||||
}
|
||||
cl->notifyChannelGroupList();
|
||||
});
|
||||
if (group_manager->deleteGroup(channel_group)) {
|
||||
serverInstance->action_logger()->group_logger.log_group_delete(this->getServerId(), this->ref(), log::GroupTarget::SERVER, log_group_type, channel_group->groupId(), channel_group->name());
|
||||
if(this->server) {
|
||||
this->server->forEachClient([&](shared_ptr<ConnectedClient> cl) {
|
||||
if(this->server->notifyClientPropertyUpdates(cl, this->server->groups->update_server_group_property(cl, true, cl->getChannel()))) {
|
||||
if(cl->update_cached_permissions()) /* update cached calculated permissions */
|
||||
cl->sendNeededPermissions(false); /* cached permissions had changed, notify the client */
|
||||
}
|
||||
cl->notifyChannelGroupList();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return command_result{error::ok};
|
||||
@@ -414,6 +508,15 @@ command_result ConnectedClient::handleCommandChannelGroupAddPerm(Command &cmd) {
|
||||
bool updateList{false};
|
||||
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
|
||||
ppermission.apply_to(channelGroup->permissions(), permission::v2::PermissionUpdateType::set_value);
|
||||
ppermission.log_update(serverInstance->action_logger()->permission_logger,
|
||||
this->getServerId(),
|
||||
this->ref(),
|
||||
log::PermissionTarget::CHANNEL_GROUP,
|
||||
permission::v2::PermissionUpdateType::set_value,
|
||||
0, "",
|
||||
channelGroup->groupId(), channelGroup->name()
|
||||
);
|
||||
|
||||
updateList |= ppermission.is_group_property();
|
||||
}
|
||||
|
||||
@@ -453,6 +556,14 @@ command_result ConnectedClient::handleCommandChannelGroupDelPerm(Command &cmd) {
|
||||
bool updateList{false};
|
||||
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
|
||||
ppermission.apply_to(channelGroup->permissions(), permission::v2::PermissionUpdateType::delete_value);
|
||||
ppermission.log_update(serverInstance->action_logger()->permission_logger,
|
||||
this->getServerId(),
|
||||
this->ref(),
|
||||
log::PermissionTarget::CHANNEL_GROUP,
|
||||
permission::v2::PermissionUpdateType::delete_value,
|
||||
0, "",
|
||||
channelGroup->groupId(), channelGroup->name()
|
||||
);
|
||||
updateList |= ppermission.is_group_property();
|
||||
}
|
||||
|
||||
@@ -685,24 +796,50 @@ command_result ConnectedClient::handleCommandChannelCreate(Command &cmd) {
|
||||
);
|
||||
}
|
||||
|
||||
for (auto &prop : cmd[0].keys()) {
|
||||
if (prop == "channel_flag_default") continue;
|
||||
if (prop == "channel_order") continue;
|
||||
if (prop == "channel_name") continue;
|
||||
if (prop == "cpid") continue;
|
||||
if (prop == "cid") continue;
|
||||
/* log channel create */
|
||||
{
|
||||
log::ChannelType log_channel_type;
|
||||
switch (created_channel->channelType()) {
|
||||
case ChannelType::permanent:
|
||||
log_channel_type = log::ChannelType::PERMANENT;
|
||||
break;
|
||||
|
||||
const auto &property = property::find<property::ChannelProperties>(prop);
|
||||
case ChannelType::semipermanent:
|
||||
log_channel_type = log::ChannelType::SEMI_PERMANENT;
|
||||
break;
|
||||
|
||||
case ChannelType::temporary:
|
||||
log_channel_type = log::ChannelType::TEMPORARY;
|
||||
break;
|
||||
}
|
||||
|
||||
serverInstance->action_logger()->channel_logger.log_channel_create(this->getServerId(), this->ref(), created_channel->channelId(), log_channel_type);
|
||||
}
|
||||
|
||||
for (auto &property_name : cmd[0].keys()) {
|
||||
if (property_name == "channel_flag_default") continue;
|
||||
if (property_name == "channel_order") continue;
|
||||
if (property_name == "channel_name") continue;
|
||||
if (property_name == "cpid") continue;
|
||||
if (property_name == "cid") continue;
|
||||
|
||||
const auto &property = property::find<property::ChannelProperties>(property_name);
|
||||
if(property == property::CHANNEL_UNDEFINED) {
|
||||
logError(this->getServerId(), "Client " + this->getDisplayName() + " tried to change a not existing channel property " + prop);
|
||||
logError(this->getServerId(), "Client " + this->getDisplayName() + " tried to change a not existing channel property " + property_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!property.validate_input(cmd[prop].as<string>())) {
|
||||
logError(this->getServerId(), "Client " + this->getDisplayName() + " tried to change a property to an invalid value. (Value: '" + cmd[prop].as<string>() + "', Property: '" + std::string{property.name} + "')");
|
||||
if(!property.validate_input(cmd[property_name].as<string>())) {
|
||||
logError(this->getServerId(), "Client " + this->getDisplayName() + " tried to change a property to an invalid value. (Value: '" + cmd[property_name].as<string>() + "', Property: '" + std::string{property.name} + "')");
|
||||
continue;
|
||||
}
|
||||
created_channel->properties()[property] = cmd[prop].as<std::string>();
|
||||
auto prop = created_channel->properties()[property];
|
||||
auto old_value = prop.value();
|
||||
auto new_value = cmd[property_name].as<std::string>();
|
||||
if(old_value == new_value)
|
||||
continue;
|
||||
prop = new_value;
|
||||
serverInstance->action_logger()->channel_logger.log_channel_edit(this->getServerId(), this->ref(), created_channel->channelId(), property, old_value, new_value);
|
||||
}
|
||||
if(created_channel->parent()) {
|
||||
if(created_channel->parent()->channelType() > created_channel->channelType())
|
||||
@@ -738,6 +875,8 @@ command_result ConnectedClient::handleCommandChannelCreate(Command &cmd) {
|
||||
logError(this->getServerId(), "Missing server's default channel admin group! Using default channel group!");
|
||||
channel_admin_group = this->server->groups->defaultGroup(GroupTarget::GROUPTARGET_CHANNEL);
|
||||
}
|
||||
|
||||
/* FIXME: Log group assignment */
|
||||
this->server->groups->setChannelGroup(this->getClientDatabaseId(), channel_admin_group, created_channel);
|
||||
|
||||
if (created_channel->channelType() == ChannelType::temporary && (this->getType() == ClientType::CLIENT_TEAMSPEAK || this->getType() == ClientType::CLIENT_WEB))
|
||||
@@ -776,11 +915,15 @@ command_result ConnectedClient::handleCommandChannelDelete(Command &cmd) {
|
||||
if(!clients.empty())
|
||||
ACTION_REQUIRES_PERMISSION(permission::b_channel_delete_flag_force, 1, channel->channelId());
|
||||
|
||||
this->server->delete_channel(channel, this->ref(), "channel deleted", channel_tree_write_lock);
|
||||
this->server->delete_channel(channel, this->ref(), "channel deleted", channel_tree_write_lock, false);
|
||||
} else {
|
||||
auto channel_ids = channel_tree->deleteChannelRoot(channel);
|
||||
this->notifyChannelDeleted(channel_ids, this->ref());
|
||||
auto deleted_channel_ids = channel_tree->deleteChannelRoot(channel);
|
||||
for(const auto& channelId : deleted_channel_ids) {
|
||||
serverInstance->action_logger()->channel_logger.log_channel_delete(0, this->ref(), channelId, channel->channelId() == channelId ? log::ChannelDeleteReason::USER_ACTION : log::ChannelDeleteReason::PARENT_DELETED);
|
||||
}
|
||||
this->notifyChannelDeleted(deleted_channel_ids, this->ref());
|
||||
}
|
||||
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
@@ -1108,9 +1251,15 @@ command_result ConnectedClient::handleCommandChannelEdit(Command &cmd) {
|
||||
for(const property::PropertyDescription* key : keys) {
|
||||
if(*key == property::CHANNEL_ORDER) {
|
||||
/* TODO: May move that up because if it fails may some other props have already be applied */
|
||||
auto old_channel_order = channel->channelOrder();
|
||||
if (!channel_tree->change_order(channel, cmd[std::string{key->name}]))
|
||||
return command_result{error::channel_invalid_order, "Can't change order id"};
|
||||
|
||||
auto channel_parent = channel->parent() ? channel->parent()->channelId() : 0;
|
||||
serverInstance->action_logger()->channel_logger.log_channel_move(this->getServerId(), this->ref(), channel->channelId(),
|
||||
channel_parent, channel_parent,
|
||||
old_channel_order, channel->channelOrder());
|
||||
|
||||
if(this->server) {
|
||||
auto parent = channel->hasParent() ? channel_tree->findLinkedChannel(channel->parent()->channelId()) : nullptr;
|
||||
auto previous = channel_tree->findLinkedChannel(channel->previousChannelId());
|
||||
@@ -1144,6 +1293,9 @@ command_result ConnectedClient::handleCommandChannelEdit(Command &cmd) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* property has already been updated as well the log has also been written */
|
||||
continue;
|
||||
} else if(*key == property::CHANNEL_FLAG_DEFAULT) {
|
||||
old_default_channel = channel_tree->getDefaultChannel();
|
||||
if(old_default_channel == channel) {
|
||||
@@ -1216,7 +1368,14 @@ command_result ConnectedClient::handleCommandChannelEdit(Command &cmd) {
|
||||
channel->permissions()->set_permission(permission::i_client_needed_talk_power, {cmd[key->name].as<int>(), 0}, permission::v2::set_value, permission::v2::do_nothing);
|
||||
}
|
||||
|
||||
channel->properties()[*key] = cmd[std::string{key->name}].string();
|
||||
auto prop = channel->properties()[*key];
|
||||
auto old_value = prop.value();
|
||||
auto new_value = cmd[std::string{key->name}].string();
|
||||
if(old_value == new_value)
|
||||
continue;
|
||||
|
||||
prop = new_value;
|
||||
serverInstance->action_logger()->channel_logger.log_channel_edit(this->getServerId(), this->ref(), channel->channelId(), *key, old_value, new_value);
|
||||
}
|
||||
if(this->server) {
|
||||
vector<property::ChannelProperties> key_vector;
|
||||
@@ -1283,9 +1442,16 @@ command_result ConnectedClient::handleCommandChannelMove(Command &cmd) {
|
||||
if(channel->parent() == parent && channel->channelOrder() == (order ? order->channelId() : 0))
|
||||
return command_result{error::ok};
|
||||
|
||||
if (channel->parent() != parent)
|
||||
auto old_parent_channel_id = channel->parent() ? channel->parent()->channelId() : 0;
|
||||
auto old_channel_order = channel->channelOrder();
|
||||
|
||||
bool change_parent{channel->parent() != parent};
|
||||
bool change_order{(order ? order->channelId() : 0) != channel->channelOrder()};
|
||||
|
||||
if (change_parent)
|
||||
ACTION_REQUIRES_PERMISSION(permission::b_channel_modify_parent, 1, channel_id);
|
||||
if ((order ? order->channelId() : 0) != channel->channelOrder())
|
||||
|
||||
if (change_order)
|
||||
ACTION_REQUIRES_PERMISSION(permission::b_channel_modify_sortorder, 1, channel_id);
|
||||
|
||||
{
|
||||
@@ -1331,6 +1497,24 @@ command_result ConnectedClient::handleCommandChannelMove(Command &cmd) {
|
||||
} while ((current_channel = dynamic_pointer_cast<ServerChannel>(current_channel->parent())));
|
||||
}
|
||||
|
||||
/* log all the updates */
|
||||
serverInstance->action_logger()->channel_logger.log_channel_move(this->getServerId(), this->ref(), channel->channelId(),
|
||||
old_parent_channel_id, channel->parent() ? channel->parent()->channelId() : 0,
|
||||
old_channel_order, channel->channelOrder());
|
||||
|
||||
for(const auto& type_update : channel_type_updates) {
|
||||
serverInstance->action_logger()->channel_logger.log_channel_edit(this->getServerId(), this->ref(), type_update->channelId(),
|
||||
property::describe(property::CHANNEL_FLAG_PERMANENT),
|
||||
"",
|
||||
type_update->properties()[property::CHANNEL_FLAG_PERMANENT].value()
|
||||
);
|
||||
serverInstance->action_logger()->channel_logger.log_channel_edit(this->getServerId(), this->ref(), type_update->channelId(),
|
||||
property::describe(property::CHANNEL_FLAG_SEMI_PERMANENT),
|
||||
"",
|
||||
type_update->properties()[property::CHANNEL_FLAG_SEMI_PERMANENT].value()
|
||||
);
|
||||
}
|
||||
|
||||
if(this->server) {
|
||||
auto self_rev = this->ref();
|
||||
this->server->forEachClient([&](const shared_ptr<ConnectedClient>& client) {
|
||||
@@ -1442,8 +1626,17 @@ command_result ConnectedClient::handleCommandChannelAddPerm(Command &cmd) {
|
||||
|
||||
auto permission_manager = channel->permissions();
|
||||
auto updateClients = false, update_join_permissions = false, update_channel_properties = false;
|
||||
auto channelId = channel->channelId();
|
||||
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
|
||||
ppermission.apply_to(permission_manager, permission::v2::PermissionUpdateType::set_value);
|
||||
ppermission.log_update(serverInstance->action_logger()->permission_logger,
|
||||
this->getServerId(),
|
||||
this->ref(),
|
||||
log::PermissionTarget::CHANNEL,
|
||||
permission::v2::PermissionUpdateType::set_value,
|
||||
channelId, channel->name(),
|
||||
0, ""
|
||||
);
|
||||
|
||||
updateClients |= ppermission.is_client_view_property();
|
||||
update_join_permissions = ppermission.permission_type() == permission::i_channel_needed_join_power;
|
||||
@@ -1480,8 +1673,17 @@ command_result ConnectedClient::handleCommandChannelDelPerm(Command &cmd) {
|
||||
|
||||
auto permission_manager = channel->permissions();
|
||||
auto updateClients = false, update_join_permissions = false, update_channel_properties = false;
|
||||
auto channelId = channel->channelId();
|
||||
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
|
||||
ppermission.apply_to(permission_manager, permission::v2::PermissionUpdateType::delete_value);
|
||||
ppermission.log_update(serverInstance->action_logger()->permission_logger,
|
||||
this->getServerId(),
|
||||
this->ref(),
|
||||
log::PermissionTarget::CHANNEL,
|
||||
permission::v2::PermissionUpdateType::delete_value,
|
||||
channelId, channel->name(),
|
||||
0, ""
|
||||
);
|
||||
|
||||
updateClients |= ppermission.is_client_view_property();
|
||||
update_join_permissions = ppermission.permission_type() == permission::i_channel_needed_join_power;
|
||||
@@ -1586,6 +1788,14 @@ command_result ConnectedClient::handleCommandChannelClientDelPerm(Command &cmd)
|
||||
bool update_view{false};
|
||||
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
|
||||
ppermission.apply_to_channel(mgr, permission::v2::PermissionUpdateType::delete_value, channel->channelId());
|
||||
ppermission.log_update(serverInstance->action_logger()->permission_logger,
|
||||
this->getServerId(),
|
||||
this->ref(),
|
||||
log::PermissionTarget::CLIENT_CHANNEL,
|
||||
permission::v2::PermissionUpdateType::delete_value,
|
||||
cldbid, "",
|
||||
channel->channelId(), channel->name()
|
||||
);
|
||||
update_view |= ppermission.is_client_view_property();
|
||||
}
|
||||
|
||||
@@ -1646,6 +1856,14 @@ command_result ConnectedClient::handleCommandChannelClientAddPerm(Command &cmd)
|
||||
bool update_view{false};
|
||||
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
|
||||
ppermission.apply_to_channel(mgr, permission::v2::PermissionUpdateType::set_value, channel->channelId());
|
||||
ppermission.log_update(serverInstance->action_logger()->permission_logger,
|
||||
this->getServerId(),
|
||||
this->ref(),
|
||||
log::PermissionTarget::CLIENT_CHANNEL,
|
||||
permission::v2::PermissionUpdateType::set_value,
|
||||
cldbid, "",
|
||||
channel->channelId(), channel->name()
|
||||
);
|
||||
update_view |= ppermission.is_client_view_property();
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "../../weblist/WebListManager.h"
|
||||
#include "../../manager/ConversationManager.h"
|
||||
#include "../../manager/PermissionNameMapper.h"
|
||||
#include "../../manager/ActionLogger.h"
|
||||
#include <cstdint>
|
||||
|
||||
#include "helpers.h"
|
||||
@@ -77,6 +78,7 @@ command_result ConnectedClient::handleCommandClientKick(Command &cmd) {
|
||||
result.emplace_result(error::client_invalid_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (client->getType() == CLIENT_MUSIC) {
|
||||
result.emplace_result(error::client_invalid_type);
|
||||
continue;
|
||||
@@ -101,11 +103,16 @@ command_result ConnectedClient::handleCommandClientKick(Command &cmd) {
|
||||
}
|
||||
|
||||
for(auto& client : clients) {
|
||||
auto old_channel = client->getChannel();
|
||||
if(!old_channel) continue;
|
||||
|
||||
if (target_channel) {
|
||||
this->server->notify_client_kick(client.client, this->ref(), cmd["reasonmsg"].as<std::string>(), target_channel);
|
||||
serverInstance->action_logger()->client_channel_logger.log_client_kick(this->getServerId(), this->ref(), client->ref(), target_channel->channelId(), target_channel->name(), old_channel->channelId(), old_channel->name());
|
||||
} else {
|
||||
this->server->notify_client_kick(client.client, this->ref(), cmd["reasonmsg"].as<std::string>(), nullptr);
|
||||
client->close_connection(system_clock::now() + seconds(1));
|
||||
serverInstance->action_logger()->client_channel_logger.log_client_kick(this->getServerId(), this->ref(), client->ref(), 0, "", old_channel->channelId(), old_channel->name());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,6 +264,9 @@ command_result ConnectedClient::handleCommandClientMove(Command &cmd) {
|
||||
true,
|
||||
server_channel_w_lock
|
||||
);
|
||||
|
||||
serverInstance->action_logger()->client_channel_logger.log_client_move(this->getServerId(), this->ref(), client->ref(), channel->channelId(), channel->name(), oldChannel->channelId(), oldChannel->name());
|
||||
|
||||
if(std::find_if(channels.begin(), channels.end(), [&](const std::shared_ptr<BasicChannel>& channel) { return &*channel == &*oldChannel; }) == channels.end())
|
||||
channels.push_back(oldChannel);
|
||||
}
|
||||
@@ -266,7 +276,7 @@ command_result ConnectedClient::handleCommandClientMove(Command &cmd) {
|
||||
server_channel_w_lock.lock();
|
||||
if(oldChannel->channelType() == ChannelType::temporary && oldChannel->properties()[property::CHANNEL_DELETE_DELAY].as<int64_t>() == 0)
|
||||
if(this->server->getClientsByChannelRoot(oldChannel, false).empty())
|
||||
this->server->delete_channel(dynamic_pointer_cast<ServerChannel>(oldChannel), this->ref(), "temporary auto delete", server_channel_w_lock);
|
||||
this->server->delete_channel(dynamic_pointer_cast<ServerChannel>(oldChannel), this->ref(), "temporary auto delete", server_channel_w_lock, true);
|
||||
if(server_channel_w_lock.owns_lock())
|
||||
server_channel_w_lock.unlock();
|
||||
}
|
||||
@@ -701,8 +711,24 @@ command_result ConnectedClient::handleCommandClientEdit(Command &cmd, const std:
|
||||
if(*key.first == property::CLIENT_IS_PRIORITY_SPEAKER) {
|
||||
client->clientPermissions->set_permission(permission::b_client_is_priority_speaker, {1, 0}, cmd["client_is_priority_speaker"].as<bool>() ? permission::v2::PermissionUpdateType::set_value : permission::v2::PermissionUpdateType::delete_value, permission::v2::PermissionUpdateType::do_nothing);
|
||||
}
|
||||
client->properties()[key.first] = cmd[0][key.second].value();
|
||||
|
||||
auto property = client->properties()[key.first];
|
||||
auto old_value = property.value();
|
||||
auto new_value = cmd[0][key.second].value();
|
||||
if(old_value == new_value)
|
||||
continue;
|
||||
|
||||
property = new_value;
|
||||
updates.push_back(key.first);
|
||||
|
||||
serverInstance->action_logger()->client_edit_logger.log_client_edit(
|
||||
this->getServerId(),
|
||||
this->ref(),
|
||||
client,
|
||||
*key.first,
|
||||
old_value,
|
||||
new_value
|
||||
);
|
||||
}
|
||||
if(update_talk_rights)
|
||||
client->updateTalkRights(client->properties()[property::CLIENT_TALK_POWER]);
|
||||
@@ -954,6 +980,15 @@ command_result ConnectedClient::handleCommandClientAddPerm(Command &cmd) {
|
||||
bool update_channels{false};
|
||||
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
|
||||
ppermission.apply_to(mgr, permission::v2::PermissionUpdateType::set_value);
|
||||
ppermission.log_update(serverInstance->action_logger()->permission_logger,
|
||||
this->getServerId(),
|
||||
this->ref(),
|
||||
log::PermissionTarget::CLIENT,
|
||||
permission::v2::PermissionUpdateType::set_value,
|
||||
cldbid, "",
|
||||
0, ""
|
||||
);
|
||||
|
||||
update_channels |= ppermission.is_client_view_property();
|
||||
}
|
||||
|
||||
@@ -989,6 +1024,14 @@ command_result ConnectedClient::handleCommandClientDelPerm(Command &cmd) {
|
||||
bool update_channels{false};
|
||||
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
|
||||
ppermission.apply_to(mgr, permission::v2::PermissionUpdateType::delete_value);
|
||||
ppermission.log_update(serverInstance->action_logger()->permission_logger,
|
||||
this->getServerId(),
|
||||
this->ref(),
|
||||
log::PermissionTarget::CLIENT,
|
||||
permission::v2::PermissionUpdateType::delete_value,
|
||||
cldbid, "",
|
||||
0, ""
|
||||
);
|
||||
update_channels |= ppermission.is_client_view_property();
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "../../weblist/WebListManager.h"
|
||||
#include "../../manager/ConversationManager.h"
|
||||
#include "../../manager/PermissionNameMapper.h"
|
||||
#include "../../manager/ActionLogger.h"
|
||||
#include "helpers.h"
|
||||
|
||||
#include <files/FileServer.h>
|
||||
@@ -185,6 +186,7 @@ command_result ConnectedClient::handleCommandFTCreateDir(Command &cmd) {
|
||||
if(!virtual_file_server) return command_result{error::file_virtual_server_not_registered};
|
||||
auto& file_system = file::server()->file_system();
|
||||
|
||||
std::shared_lock channel_tree_lock{this->server->channel_tree_lock};
|
||||
auto channel = this->server->channelTree->findChannel(cmd["cid"].as<ChannelId>());
|
||||
if (!channel)
|
||||
return command_result{error::channel_invalid_id};
|
||||
@@ -194,6 +196,7 @@ command_result ConnectedClient::handleCommandFTCreateDir(Command &cmd) {
|
||||
|
||||
if(!channel->permission_granted(permission::i_ft_needed_directory_create_power, this->calculate_permission(permission::i_ft_directory_create_power, channel->channelId()), true))
|
||||
return command_result{permission::i_ft_directory_create_power};
|
||||
channel_tree_lock.unlock();
|
||||
|
||||
auto create_result = file_system.create_channel_directory(virtual_file_server, channel->channelId(), cmd["dirname"].string());
|
||||
if(!create_result->wait_for(kFileAPITimeout))
|
||||
@@ -217,6 +220,8 @@ command_result ConnectedClient::handleCommandFTCreateDir(Command &cmd) {
|
||||
}
|
||||
}
|
||||
|
||||
serverInstance->action_logger()->file_logger.log_file_directory_create(this->getServerId(), this->ref(), channel->channelId(), cmd["dirname"].string());
|
||||
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
@@ -234,9 +239,12 @@ command_result ConnectedClient::handleCommandFTDeleteFile(Command &cmd) {
|
||||
ts::command_result_bulk response{};
|
||||
response.emplace_result_n(cmd.bulkCount(), error::ok);
|
||||
|
||||
std::vector<std::tuple<uint64_t, std::string>> file_log_info{};
|
||||
|
||||
auto file_path = cmd["path"].string();
|
||||
std::shared_ptr<file::ExecuteResponse<file::filesystem::FileDeleteError, file::filesystem::FileDeleteResponse>> delete_response{};
|
||||
if (cmd[0].has("cid") && cmd["cid"] != 0) {
|
||||
std::shared_lock channel_tree_lock{this->server->channel_tree_lock};
|
||||
auto channel = this->server->channelTree->findChannel(cmd["cid"].as<ChannelId>());
|
||||
if (!channel)
|
||||
return command_result{error::channel_invalid_id};
|
||||
@@ -249,8 +257,11 @@ command_result ConnectedClient::handleCommandFTDeleteFile(Command &cmd) {
|
||||
|
||||
std::vector<std::string> delete_files{};
|
||||
delete_files.reserve(cmd.bulkCount());
|
||||
for(size_t index{0}; index < cmd.bulkCount(); index++)
|
||||
file_log_info.reserve(cmd.bulkCount());
|
||||
for(size_t index{0}; index < cmd.bulkCount(); index++) {
|
||||
delete_files.push_back(file_path + "/" + cmd[index]["name"].string());
|
||||
file_log_info.emplace_back(channel->channelId(), file_path + "/" + cmd[index]["name"].string());
|
||||
}
|
||||
|
||||
delete_response = file_system.delete_channel_files(virtual_file_server, channel->channelId(), delete_files);
|
||||
} else {
|
||||
@@ -261,6 +272,7 @@ command_result ConnectedClient::handleCommandFTDeleteFile(Command &cmd) {
|
||||
|
||||
std::vector<std::string> delete_files{};
|
||||
delete_files.reserve(cmd.bulkCount());
|
||||
file_log_info.reserve(cmd.bulkCount());
|
||||
for(size_t index{0}; index < cmd.bulkCount(); index++) {
|
||||
auto file_name = cmd[index]["name"].string();
|
||||
if(!file_name.starts_with("/icon_")) {
|
||||
@@ -269,6 +281,7 @@ command_result ConnectedClient::handleCommandFTDeleteFile(Command &cmd) {
|
||||
}
|
||||
|
||||
delete_files.push_back(file_name);
|
||||
file_log_info.emplace_back(0, file_name);
|
||||
}
|
||||
|
||||
delete_response = file_system.delete_icons(virtual_file_server, delete_files);
|
||||
@@ -281,6 +294,7 @@ command_result ConnectedClient::handleCommandFTDeleteFile(Command &cmd) {
|
||||
|
||||
std::vector<std::string> delete_files{};
|
||||
delete_files.reserve(cmd.bulkCount());
|
||||
file_log_info.reserve(cmd.bulkCount());
|
||||
for(size_t index{0}; index < cmd.bulkCount(); index++) {
|
||||
auto file_name = cmd[index]["name"].string();
|
||||
if(!file_name.starts_with("/avatar_")) {
|
||||
@@ -311,9 +325,12 @@ command_result ConnectedClient::handleCommandFTDeleteFile(Command &cmd) {
|
||||
}
|
||||
|
||||
delete_files.push_back("/avatar_" + avId);
|
||||
file_log_info.emplace_back(0, "/avatar_" + avId);
|
||||
} else {
|
||||
this->properties()[property::CLIENT_FLAG_AVATAR] = "";
|
||||
this->server->notifyClientPropertyUpdates(_this.lock(), deque<property::ClientProperties>{property::CLIENT_FLAG_AVATAR});
|
||||
delete_files.push_back("/avatar_" + this->getAvatarId());
|
||||
file_log_info.emplace_back(0, "/avatar_" + this->getAvatarId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,13 +358,17 @@ command_result ConnectedClient::handleCommandFTDeleteFile(Command &cmd) {
|
||||
|
||||
const auto& file_status = delete_response->response();
|
||||
size_t bulk_index{0};
|
||||
for(const auto& file : file_status.delete_results) {
|
||||
for(size_t index{0}; index < file_status.delete_results.size(); index++) {
|
||||
const auto& file = file_status.delete_results[index];
|
||||
const auto& log_file_info = file_log_info[index];
|
||||
|
||||
while(response.response(bulk_index).error_code() != error::ok)
|
||||
bulk_index++;
|
||||
|
||||
using Status = file::filesystem::FileDeleteResponse::StatusType;
|
||||
switch (file.status) {
|
||||
case Status::SUCCESS:
|
||||
serverInstance->action_logger()->file_logger.log_file_delete(this->getServerId(), this->ref(), std::get<0>(log_file_info), std::get<1>(log_file_info));
|
||||
/* we already emplaced success */
|
||||
break;
|
||||
|
||||
@@ -491,8 +512,7 @@ command_result ConnectedClient::handleCommandFTGetFileInfo(ts::Command &cmd) {
|
||||
auto avId = hex::hex(base64::decode(uid), 'a', 'q');
|
||||
delete_files.push_back("/avatar_" + avId);
|
||||
} else {
|
||||
this->properties()[property::CLIENT_FLAG_AVATAR] = "";
|
||||
this->server->notifyClientPropertyUpdates(_this.lock(), deque<property::ClientProperties>{property::CLIENT_FLAG_AVATAR});
|
||||
delete_files.push_back("/avatar_" + this->getAvatarId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -641,8 +661,9 @@ command_result ConnectedClient::handleCommandFTInitUpload(ts::Command &cmd) {
|
||||
return command_result{error::file_transfer_client_quota_exceeded};
|
||||
}
|
||||
|
||||
|
||||
ChannelId log_channel_id{0};
|
||||
if(cmd[0].has("cid") && cmd["cid"] != 0) { //Channel
|
||||
std::shared_lock channel_tree_lock{this->server->channel_tree_lock};
|
||||
auto channel = this->server->channelTree->findChannel(cmd["cid"].as<ChannelId>());
|
||||
if (!channel)
|
||||
return command_result{error::channel_invalid_id, "Cant resolve channel"};
|
||||
@@ -652,6 +673,7 @@ command_result ConnectedClient::handleCommandFTInitUpload(ts::Command &cmd) {
|
||||
|
||||
ACTION_REQUIRES_CHANNEL_PERMISSION(channel, permission::i_ft_needed_file_upload_power, permission::i_ft_file_upload_power, true);
|
||||
transfer_response = file::server()->file_transfer().initialize_channel_transfer(file::transfer::Transfer::DIRECTION_UPLOAD, virtual_file_server, channel->channelId(), info);
|
||||
log_channel_id = channel->channelId();
|
||||
} else {
|
||||
if (cmd["path"].string().empty() && cmd["name"].string().starts_with("/icon_")) {
|
||||
auto max_size = this->calculate_permission(permission::i_max_icon_filesize, 0);
|
||||
@@ -727,6 +749,7 @@ command_result ConnectedClient::handleCommandFTInitUpload(ts::Command &cmd) {
|
||||
result.put_unchecked(0, "proto", "1");
|
||||
this->sendCommand(result);
|
||||
|
||||
serverInstance->action_logger()->file_logger.log_file_upload(this->getServerId(), this->ref(), log_channel_id, info.file_path);
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
@@ -781,7 +804,9 @@ command_result ConnectedClient::handleCommandFTInitDownload(ts::Command &cmd) {
|
||||
info.client_id = this->getClientId();
|
||||
info.max_concurrent_transfers = kMaxClientTransfers;
|
||||
|
||||
ChannelId log_channel_id{0};
|
||||
if(cmd[0].has("cid") && cmd["cid"] != 0) { //Channel
|
||||
std::shared_lock channel_tree_lock{this->server->channel_tree_lock};
|
||||
auto channel = this->server->channelTree->findChannel(cmd["cid"].as<ChannelId>());
|
||||
if (!channel)
|
||||
return command_result{error::channel_invalid_id};
|
||||
@@ -791,6 +816,7 @@ command_result ConnectedClient::handleCommandFTInitDownload(ts::Command &cmd) {
|
||||
|
||||
ACTION_REQUIRES_CHANNEL_PERMISSION(channel, permission::i_ft_needed_file_download_power, permission::i_ft_file_download_power, true);
|
||||
transfer_response = file::server()->file_transfer().initialize_channel_transfer(file::transfer::Transfer::DIRECTION_DOWNLOAD, virtual_file_server, channel->channelId(), info);
|
||||
log_channel_id = channel->channelId();
|
||||
} else {
|
||||
if (cmd["path"].as<std::string>().empty() && cmd["name"].string().starts_with("/icon_")) {
|
||||
transfer_response = file::server()->file_transfer().initialize_icon_transfer(file::transfer::Transfer::DIRECTION_DOWNLOAD, virtual_file_server, info);
|
||||
@@ -859,6 +885,7 @@ command_result ConnectedClient::handleCommandFTInitDownload(ts::Command &cmd) {
|
||||
result.put_unchecked(0, "seekpos", transfer->file_offset);
|
||||
this->sendCommand(result);
|
||||
|
||||
serverInstance->action_logger()->file_logger.log_file_download(this->getServerId(), this->ref(), log_channel_id, info.file_path);
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
@@ -881,6 +908,7 @@ command_result ConnectedClient::handleCommandFTRenameFile(ts::Command &cmd) {
|
||||
auto channel_id = cmd["cid"].as<ChannelId>();
|
||||
auto target_channel_id = cmd[0].has("tcid") ? cmd["tcid"].as<ChannelId>() : channel_id;
|
||||
|
||||
std::shared_lock channel_tree_lock{this->server->channel_tree_lock};
|
||||
auto channel = this->server->channelTree->findChannel(channel_id);
|
||||
if (!channel)
|
||||
return command_result{error::channel_invalid_id};
|
||||
@@ -900,6 +928,7 @@ command_result ConnectedClient::handleCommandFTRenameFile(ts::Command &cmd) {
|
||||
|
||||
ACTION_REQUIRES_CHANNEL_PERMISSION(targetChannel, permission::i_ft_needed_file_rename_power, permission::i_ft_file_rename_power, true);
|
||||
}
|
||||
channel_tree_lock.unlock();
|
||||
|
||||
|
||||
auto rename_response = file::server()->file_system().rename_channel_file(virtual_file_server, channel_id, cmd["oldname"].string(), target_channel_id, cmd["newname"].string());
|
||||
@@ -933,6 +962,7 @@ command_result ConnectedClient::handleCommandFTRenameFile(ts::Command &cmd) {
|
||||
}
|
||||
}
|
||||
|
||||
serverInstance->action_logger()->file_logger.log_file_rename(this->getServerId(), this->ref(), channel_id, cmd["oldname"].string(), target_channel_id, cmd["newname"].string());
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "../../weblist/WebListManager.h"
|
||||
#include "../../manager/ConversationManager.h"
|
||||
#include "../../manager/PermissionNameMapper.h"
|
||||
#include "../../manager/ActionLogger.h"
|
||||
#include <experimental/filesystem>
|
||||
#include <cstdint>
|
||||
#include <StringVariable.h>
|
||||
@@ -211,6 +212,9 @@ command_result ConnectedClient::handleCommand(Command &cmd) {
|
||||
else if (command == "help") return this->handleCommandHelp(cmd);
|
||||
|
||||
else if (command == "logview") return this->handleCommandLogView(cmd);
|
||||
else if (command == "logquery") return this->handleCommandLogQuery(cmd);
|
||||
else if (command == "logadd") return this->handleCommandLogAdd(cmd);
|
||||
|
||||
else if (command == "servergroupautoaddperm") return this->handleCommandServerGroupAutoAddPerm(cmd);
|
||||
else if (command == "servergroupautodelperm") return this->handleCommandServerGroupAutoDelPerm(cmd);
|
||||
|
||||
@@ -448,23 +452,28 @@ command_result ConnectedClient::handleCommandSetClientChannelGroup(Command &cmd)
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<GroupAssignment> old_group;
|
||||
{
|
||||
auto old_group = this->server->groups->getChannelGroupExact(target_cldbid, channel, false);
|
||||
old_group = this->server->groups->getChannelGroupExact(target_cldbid, channel, false);
|
||||
if(old_group) {
|
||||
auto channel_group_member_remove_power = this->calculate_permission(permission::i_channel_group_member_remove_power, channel_id);
|
||||
if(!serverGroup->permission_granted(permission::i_channel_group_needed_member_remove_power, channel_group_member_remove_power, true)) {
|
||||
if(!old_group->group->permission_granted(permission::i_channel_group_needed_member_remove_power, channel_group_member_remove_power, true)) {
|
||||
if(target_cldbid != this->getClientDatabaseId())
|
||||
return command_result{permission::i_channel_group_member_remove_power};
|
||||
|
||||
auto channel_group_self_remove_power = this->calculate_permission(permission::i_channel_group_self_remove_power, channel_id);
|
||||
if(!serverGroup->permission_granted(permission::i_channel_group_needed_member_remove_power, channel_group_self_remove_power, true))
|
||||
if(!old_group->group->permission_granted(permission::i_channel_group_needed_member_remove_power, channel_group_self_remove_power, true))
|
||||
return command_result{permission::i_channel_group_self_remove_power};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->server->groups->setChannelGroup(target_cldbid, serverGroup, channel);
|
||||
|
||||
std::shared_ptr<ConnectedClient> connected_client{};
|
||||
for (const auto &targetClient : this->server->findClientsByCldbId(target_cldbid)) {
|
||||
connected_client = targetClient;
|
||||
|
||||
unique_lock client_channel_lock_w(targetClient->channel_lock);
|
||||
auto updates = this->server->groups->update_server_group_property(targetClient, false, targetClient->getChannel()); /* needs a write lock */
|
||||
client_channel_lock_w.unlock();
|
||||
@@ -487,6 +496,21 @@ command_result ConnectedClient::handleCommandSetClientChannelGroup(Command &cmd)
|
||||
targetClient->updateChannelClientProperties(false, true);
|
||||
}
|
||||
|
||||
if(old_group) {
|
||||
serverInstance->action_logger()->group_assignment_logger.log_group_assignment_remove(this->getServerId(),
|
||||
this->ref(), log::GroupTarget::CHANNEL,
|
||||
old_group->group->groupId(), old_group->group->name(),
|
||||
target_cldbid, connected_client ? connected_client->getDisplayName() : ""
|
||||
);
|
||||
}
|
||||
if(serverGroup != this->server->groups->defaultGroup(GroupTarget::GROUPTARGET_CHANNEL)) {
|
||||
serverInstance->action_logger()->group_assignment_logger.log_group_assignment_add(this->getServerId(),
|
||||
this->ref(), log::GroupTarget::CHANNEL,
|
||||
serverGroup->groupId(), serverGroup->name(),
|
||||
target_cldbid, connected_client ? connected_client->getDisplayName() : ""
|
||||
);
|
||||
}
|
||||
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
@@ -684,8 +708,9 @@ command_result ConnectedClient::handleCommandBanAdd(Command &cmd) {
|
||||
bool banned = false;
|
||||
if(existing) {
|
||||
if(existing->invokerDbId == this->getClientDatabaseId()) {
|
||||
if(existing->until == until) return command_result{error::database_duplicate_entry};
|
||||
else {
|
||||
if(existing->until == until) {
|
||||
return command_result{error::database_duplicate_entry};
|
||||
} else {
|
||||
existing->until = until;
|
||||
serverInstance->banManager()->updateBan(existing);
|
||||
banned = true;
|
||||
@@ -694,7 +719,9 @@ command_result ConnectedClient::handleCommandBanAdd(Command &cmd) {
|
||||
serverInstance->banManager()->unban(existing);
|
||||
}
|
||||
}
|
||||
if(!banned) serverInstance->banManager()->registerBan(sid, this->getClientDatabaseId(), banreason, uid, ip, name, hwid, until);
|
||||
if(!banned) {
|
||||
serverInstance->banManager()->registerBan(sid, this->getClientDatabaseId(), banreason, uid, ip, name, hwid, until);
|
||||
}
|
||||
|
||||
for(auto server : (this->server ? std::deque<shared_ptr<VirtualServer>>{this->server} : serverInstance->getVoiceServerManager()->serverInstances()))
|
||||
server->testBanStateChange(_this.lock());
|
||||
@@ -1934,19 +1961,21 @@ command_result ConnectedClient::handleCommandPermReset(ts::Command& cmd) {
|
||||
command_result ConnectedClient::handleCommandLogView(ts::Command& cmd) {
|
||||
CMD_CHK_AND_INC_FLOOD_POINTS(50);
|
||||
|
||||
auto lagacy = this->getType() == CLIENT_TEAMSPEAK || cmd.hasParm("lagacy") || cmd.hasParm("legacy");
|
||||
string log_path;
|
||||
ServerId target_server = cmd[0].has("instance") && cmd["instance"].as<bool>() ? (ServerId) 0 : this->getServerId();
|
||||
string server_identifier;
|
||||
if(target_server > 0)
|
||||
server_identifier = to_string(target_server);
|
||||
else server_identifier = "[A-Z]{0,7}";
|
||||
|
||||
if(target_server == 0)
|
||||
ACTION_REQUIRES_INSTANCE_PERMISSION(permission::b_serverinstance_log_view, 1);
|
||||
else
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_log_view, 1);
|
||||
|
||||
auto lagacy = this->getType() == CLIENT_TEAMSPEAK || cmd.hasParm("lagacy") || cmd.hasParm("legacy");
|
||||
#if 0
|
||||
string log_path;
|
||||
string server_identifier;
|
||||
if(target_server > 0)
|
||||
server_identifier = to_string(target_server);
|
||||
else
|
||||
server_identifier = "[A-Z]{0,7}";
|
||||
|
||||
for(const auto& sink : logger::logger(target_server)->sinks()) {
|
||||
if(dynamic_pointer_cast<spdlog::sinks::rotating_file_sink_mt>(sink)) {
|
||||
log_path = dynamic_pointer_cast<spdlog::sinks::rotating_file_sink_mt>(sink)->filename();
|
||||
@@ -2077,7 +2106,127 @@ command_result ConnectedClient::handleCommandLogView(ts::Command& cmd) {
|
||||
}
|
||||
}
|
||||
this->sendCommand(result);
|
||||
#else
|
||||
constexpr static std::array<std::string_view, 5> log_output{
|
||||
"The command 'logview' is not supported anymore.",
|
||||
"In order to lookup the server actions use 'logquery'.",
|
||||
"",
|
||||
"If you need to lookup the TeaSpeak - Server logs, please visit the 'logs/' folder,",
|
||||
"located at your TeaSpeak installation folder. All logs could be found there."
|
||||
};
|
||||
|
||||
command_builder result{this->getExternalType() == ClientType::CLIENT_TEAMSPEAK ? "notifyserverlog" : ""};
|
||||
size_t index{0};
|
||||
if(lagacy) {
|
||||
for(const auto& message : log_output) {
|
||||
std::string line{"2020-06-27 00:00.0000|CRITICAL|Server Instance | |"};
|
||||
line += message;
|
||||
result.put_unchecked(index++, "l", line);
|
||||
}
|
||||
} else {
|
||||
for(const auto& message : log_output) {
|
||||
std::string line{"[2020-06-27 00:00:00][ERROR] "};
|
||||
line += message;
|
||||
result.put_unchecked(index++, "l", line);
|
||||
}
|
||||
}
|
||||
this->sendCommand(result);
|
||||
#endif
|
||||
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
command_result ConnectedClient::handleCommandLogQuery(ts::Command &cmd) {
|
||||
CMD_CHK_AND_INC_FLOOD_POINTS(50);
|
||||
|
||||
uint64_t target_server = (cmd[0].has("instance") && cmd["instance"].as<bool>()) || cmd.hasParm("instance") ? (ServerId) 0 : this->getServerId();
|
||||
if(target_server == 0) {
|
||||
ACTION_REQUIRES_INSTANCE_PERMISSION(permission::b_serverinstance_log_view, 1);
|
||||
} else {
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_log_view, 1);
|
||||
}
|
||||
|
||||
std::chrono::system_clock::time_point timestamp_begin{}, timestamp_end{};
|
||||
|
||||
if(cmd[0].has("begin"))
|
||||
timestamp_begin += std::chrono::milliseconds{cmd["begin"].as<uint64_t>()};
|
||||
|
||||
if(cmd[0].has("end"))
|
||||
timestamp_end += std::chrono::milliseconds{cmd["end"].as<uint64_t>()};
|
||||
|
||||
if(timestamp_begin <= timestamp_end && timestamp_begin.time_since_epoch().count() != 0)
|
||||
return command_result{error::parameter_constraint_violation, "begin > end"};
|
||||
|
||||
size_t limit{100};
|
||||
if(cmd[0].has("limit"))
|
||||
limit = std::min((size_t) 2000, cmd["limit"].as<size_t>());
|
||||
|
||||
std::vector<log::LoggerGroup> groups{};
|
||||
if(cmd[0].has("groups")) {
|
||||
auto groups_string = cmd["groups"].string();
|
||||
size_t offset{0}, findex;
|
||||
do {
|
||||
findex = groups_string.find(',', offset);
|
||||
|
||||
auto group_name = groups_string.substr(offset, findex - offset);
|
||||
offset = findex + 1;
|
||||
|
||||
|
||||
size_t index{0};
|
||||
for(; index < (size_t) log::LoggerGroup::MAX; index++) {
|
||||
auto group = static_cast<log::LoggerGroup>(index);
|
||||
if(log::kLoggerGroupName[(int) group] == group_name) {
|
||||
if(std::find(groups.begin(), groups.end(), group) != groups.end())
|
||||
return command_result{error::parameter_invalid, "groups"};
|
||||
|
||||
groups.push_back(group);
|
||||
}
|
||||
}
|
||||
|
||||
if(index == (size_t) log::LoggerGroup::MAX)
|
||||
return command_result{error::parameter_invalid, "groups"};
|
||||
} while(offset != 0);
|
||||
}
|
||||
|
||||
auto result = serverInstance->action_logger()->query(groups, target_server, timestamp_begin, timestamp_end, limit);
|
||||
if(result.empty())
|
||||
return command_result{error::database_empty_result};
|
||||
|
||||
command_builder notify{this->notify_response_command("notifylogquery")};
|
||||
size_t index{0};
|
||||
size_t threshold = this->getType() == ClientType::CLIENT_QUERY ? (size_t) -1 : 4096; /* limit each command to 4096 bytes */
|
||||
for(log::LogEntryInfo& entry : result) {
|
||||
notify.set_bulk(index, std::move(entry.info));
|
||||
if(index == 0)
|
||||
notify.put_unchecked(0, "sid", this->getServerId());
|
||||
|
||||
if(notify.current_size() > threshold) {
|
||||
this->sendCommand(notify);
|
||||
notify.reset();
|
||||
index = 0;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
if(index> 0)
|
||||
this->sendCommand(notify);
|
||||
|
||||
if(this->getType() != ClientType::CLIENT_QUERY)
|
||||
this->sendCommand(command_builder{"notifylogqueryfinished"});
|
||||
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
command_result ConnectedClient::handleCommandLogAdd(ts::Command& cmd) {
|
||||
CMD_CHK_AND_INC_FLOOD_POINTS(50);
|
||||
|
||||
uint64_t target_server = cmd[0].has("instance") && cmd["instance"].as<bool>() ? (ServerId) 0 : this->getServerId();
|
||||
if(target_server == 0) {
|
||||
ACTION_REQUIRES_INSTANCE_PERMISSION(permission::b_serverinstance_log_add, 1);
|
||||
} else {
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_log_add, 1);
|
||||
}
|
||||
|
||||
serverInstance->action_logger()->custom_logger.add_log_message(target_server, this->ref(), cmd["msg"]);
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
|
||||
@@ -561,8 +561,17 @@ command_result ConnectedClient::handleCommandPlaylistAddPerm(ts::Command &cmd) {
|
||||
if(!pparser.validate(this->ref(), 0))
|
||||
return pparser.build_command_result();
|
||||
|
||||
for(const auto& ppermission : pparser.iterate_valid_permissions())
|
||||
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
|
||||
ppermission.apply_to(playlist->permission_manager(), permission::v2::PermissionUpdateType::set_value);
|
||||
ppermission.log_update(serverInstance->action_logger()->permission_logger,
|
||||
this->getServerId(),
|
||||
this->ref(),
|
||||
log::PermissionTarget::PLAYLIST,
|
||||
permission::v2::PermissionUpdateType::set_value,
|
||||
playlist->playlist_id(), "",
|
||||
0, ""
|
||||
);
|
||||
}
|
||||
|
||||
return pparser.build_command_result();
|
||||
}
|
||||
@@ -582,8 +591,17 @@ command_result ConnectedClient::handleCommandPlaylistDelPerm(ts::Command &cmd) {
|
||||
if(!pparser.validate(this->ref(), 0))
|
||||
return pparser.build_command_result();
|
||||
|
||||
for(const auto& ppermission : pparser.iterate_valid_permissions())
|
||||
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
|
||||
ppermission.apply_to(playlist->permission_manager(), permission::v2::PermissionUpdateType::delete_value);
|
||||
ppermission.log_update(serverInstance->action_logger()->permission_logger,
|
||||
this->getServerId(),
|
||||
this->ref(),
|
||||
log::PermissionTarget::PLAYLIST,
|
||||
permission::v2::PermissionUpdateType::delete_value,
|
||||
playlist->playlist_id(), "",
|
||||
0, ""
|
||||
);
|
||||
}
|
||||
|
||||
return pparser.build_command_result();
|
||||
}
|
||||
@@ -705,8 +723,17 @@ command_result ConnectedClient::handleCommandPlaylistClientAddPerm(ts::Command &
|
||||
if(!pparser.validate(this->ref(), this->getClientDatabaseId()))
|
||||
return pparser.build_command_result();
|
||||
|
||||
for(const auto& ppermission : pparser.iterate_valid_permissions())
|
||||
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
|
||||
ppermission.apply_to_channel(playlist->permission_manager(), permission::v2::PermissionUpdateType::set_value, client_id);
|
||||
ppermission.log_update(serverInstance->action_logger()->permission_logger,
|
||||
this->getServerId(),
|
||||
this->ref(),
|
||||
log::PermissionTarget::PLAYLIST_CLIENT,
|
||||
permission::v2::PermissionUpdateType::set_value,
|
||||
playlist->playlist_id(), "",
|
||||
client_id, ""
|
||||
);
|
||||
}
|
||||
|
||||
return pparser.build_command_result();
|
||||
}
|
||||
@@ -730,8 +757,17 @@ command_result ConnectedClient::handleCommandPlaylistClientDelPerm(ts::Command &
|
||||
if(!pparser.validate(this->ref(), this->getClientDatabaseId()))
|
||||
return pparser.build_command_result();
|
||||
|
||||
for(const auto& ppermission : pparser.iterate_valid_permissions())
|
||||
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
|
||||
ppermission.apply_to_channel(playlist->permission_manager(), permission::v2::PermissionUpdateType::delete_value, client_id);
|
||||
ppermission.log_update(serverInstance->action_logger()->permission_logger,
|
||||
this->getServerId(),
|
||||
this->ref(),
|
||||
log::PermissionTarget::PLAYLIST_CLIENT,
|
||||
permission::v2::PermissionUpdateType::delete_value,
|
||||
playlist->playlist_id(), "",
|
||||
client_id, ""
|
||||
);
|
||||
}
|
||||
|
||||
return pparser.build_command_result();
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "../../weblist/WebListManager.h"
|
||||
#include "../../manager/ConversationManager.h"
|
||||
#include "../../manager/PermissionNameMapper.h"
|
||||
#include "../../manager/ActionLogger.h"
|
||||
|
||||
#include "helpers.h"
|
||||
#include "./bulk_parsers.h"
|
||||
@@ -67,6 +68,7 @@ command_result ConnectedClient::handleCommandServerEdit(Command &cmd) {
|
||||
target_server = serverInstance->getVoiceServerManager()->findServerById(cmd["sid"]);
|
||||
if(!target_server && cmd["sid"].as<ServerId>() != 0) return command_result{error::server_invalid_id};
|
||||
}
|
||||
ServerId serverId = target_server ? target_server->serverId : 0;
|
||||
|
||||
auto cache = make_shared<CalculateCache>();
|
||||
map<string, string> toApplay;
|
||||
@@ -220,10 +222,13 @@ command_result ConnectedClient::handleCommandServerEdit(Command &cmd) {
|
||||
logError(target_server ? target_server->getServerId() : 0, "Client " + this->getDisplayName() + " tried to change a property to an invalid value. (Value: '" + elm.second + "', Property: '" + std::string{info.name} + "')");
|
||||
continue;
|
||||
}
|
||||
if(target_server)
|
||||
target_server->properties()[info] = elm.second;
|
||||
else
|
||||
(*serverInstance->getDefaultServerProperties())[info] = elm.second;
|
||||
|
||||
auto property = target_server ? target_server->properties()[info] : (*serverInstance->getDefaultServerProperties())[info];
|
||||
if(property.value() == elm.second)
|
||||
continue;
|
||||
auto old_value = property.value();
|
||||
property = elm.second;
|
||||
serverInstance->action_logger()->server_edit_logger.log_server_edit(serverId, this->ref(), info, old_value, elm.second);
|
||||
keys.push_back(elm.first);
|
||||
|
||||
group_update |= info == property::VIRTUALSERVER_DEFAULT_SERVER_GROUP || info == property::VIRTUALSERVER_DEFAULT_CHANNEL_GROUP || info == property::VIRTUALSERVER_DEFAULT_MUSIC_GROUP;
|
||||
@@ -301,23 +306,33 @@ command_result ConnectedClient::handleCommandServerGroupAdd(Command &cmd) {
|
||||
|
||||
if(cmd["name"].string().empty()) return command_result{error::parameter_invalid};
|
||||
|
||||
log::GroupType log_group_type;
|
||||
if(cmd["type"].as<GroupType>() == GroupType::GROUP_TYPE_QUERY) {
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_serverinstance_modify_querygroup, 1);
|
||||
log_group_type = log::GroupType::QUERY;
|
||||
} else if(cmd["type"].as<GroupType>() == GroupType::GROUP_TYPE_TEMPLATE) {
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_serverinstance_modify_templates, 1);
|
||||
} else if(!this->server) return command_result{error::parameter_invalid, "you cant create normal groups on the template server!"};
|
||||
log_group_type = log::GroupType::TEMPLATE;
|
||||
} else {
|
||||
if(!this->server)
|
||||
return command_result{error::parameter_invalid, "you cant create normal groups on the template server!"};
|
||||
log_group_type = log::GroupType::NORMAL;
|
||||
}
|
||||
|
||||
auto group_manager = this->server ? this->server->getGroupManager() : serverInstance->getGroupManager().get();
|
||||
for(const auto& gr : group_manager->availableServerGroups(true))
|
||||
if(gr->name() == cmd["name"].string() && gr->target() == GroupTarget::GROUPTARGET_SERVER) return command_result{error::parameter_invalid, "Group already exists"};
|
||||
auto group = group_manager->createGroup(GroupTarget::GROUPTARGET_SERVER, cmd["type"].as<GroupType>(), cmd["name"].string());
|
||||
if (group) {
|
||||
group->permissions()->set_permission(permission::b_group_is_permanent, {1,0}, permission::v2::set_value, permission::v2::do_nothing);
|
||||
if(this->server)
|
||||
this->server->forEachClient([](shared_ptr<ConnectedClient> cl) {
|
||||
cl->notifyServerGroupList();
|
||||
});
|
||||
} else return command_result{error::vs_critical};
|
||||
if(!group)
|
||||
return command_result{error::vs_critical};
|
||||
|
||||
group->permissions()->set_permission(permission::b_group_is_permanent, {1,0}, permission::v2::set_value, permission::v2::do_nothing);
|
||||
if(this->server) {
|
||||
this->server->forEachClient([](shared_ptr<ConnectedClient> cl) {
|
||||
cl->notifyServerGroupList();
|
||||
});
|
||||
}
|
||||
serverInstance->action_logger()->group_logger.log_group_create(this->getServerId(), this->ref(), log::GroupTarget::SERVER, log_group_type, group->groupId(), group->name(), 0, "");
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
@@ -379,6 +394,28 @@ command_result ConnectedClient::handleCommandServerGroupCopy(Command &cmd) {
|
||||
if(!group_manager->copyGroupPermissions(source_group, target_group))
|
||||
return command_result{error::vs_critical, "failed to copy group permissions"};
|
||||
|
||||
|
||||
log::GroupType log_group_type;
|
||||
switch (target_group->type()) {
|
||||
case GroupType::GROUP_TYPE_QUERY:
|
||||
log_group_type = log::GroupType::QUERY;
|
||||
break;
|
||||
|
||||
case GroupType::GROUP_TYPE_TEMPLATE:
|
||||
log_group_type = log::GroupType::TEMPLATE;
|
||||
break;
|
||||
|
||||
case GroupType::GROUP_TYPE_NORMAL:
|
||||
log_group_type = log::GroupType::NORMAL;
|
||||
break;
|
||||
|
||||
default:
|
||||
return command_result{error::parameter_invalid, "type"};
|
||||
}
|
||||
|
||||
serverInstance->action_logger()->group_logger.log_group_permission_copy(target_group->type() != GroupType::GROUP_TYPE_NORMAL ? 0 : this->getServerId(),
|
||||
this->ref(), log::GroupTarget::SERVER, log_group_type, target_group->groupId(), target_group->name(), source_group->groupId(), source_group->name());
|
||||
|
||||
global_update = !this->server || !group_manager->isLocalGroup(target_group);
|
||||
} else {
|
||||
//Copy a new group
|
||||
@@ -389,6 +426,23 @@ command_result ConnectedClient::handleCommandServerGroupCopy(Command &cmd) {
|
||||
if(result != permission::undefined)
|
||||
return command_result{result};
|
||||
}
|
||||
log::GroupType log_group_type;
|
||||
switch (target_type) {
|
||||
case GroupType::GROUP_TYPE_QUERY:
|
||||
log_group_type = log::GroupType::QUERY;
|
||||
break;
|
||||
|
||||
case GroupType::GROUP_TYPE_TEMPLATE:
|
||||
log_group_type = log::GroupType::TEMPLATE;
|
||||
break;
|
||||
|
||||
case GroupType::GROUP_TYPE_NORMAL:
|
||||
log_group_type = log::GroupType::NORMAL;
|
||||
break;
|
||||
|
||||
default:
|
||||
return command_result{error::parameter_invalid, "type"};
|
||||
}
|
||||
|
||||
if(!ref_server && target_type == GroupType::GROUP_TYPE_NORMAL)
|
||||
return command_result{error::parameter_invalid, "You cant create normal groups on the template server!"};
|
||||
@@ -400,6 +454,8 @@ command_result ConnectedClient::handleCommandServerGroupCopy(Command &cmd) {
|
||||
if(target_group_id == 0)
|
||||
return command_result{error::vs_critical, "failed to copy group"};
|
||||
|
||||
serverInstance->action_logger()->group_logger.log_group_create(target_type != GroupType::GROUP_TYPE_NORMAL ? 0 : this->getServerId(),
|
||||
this->ref(), log::GroupTarget::SERVER, log_group_type, target_group_id, cmd["name"].string(), source_group->groupId(), source_group->name());
|
||||
if(this->getType() == ClientType::CLIENT_QUERY) {
|
||||
Command notify("");
|
||||
notify["sgid"] = target_group_id;
|
||||
@@ -428,13 +484,20 @@ command_result ConnectedClient::handleCommandServerGroupRename(Command &cmd) {
|
||||
ACTION_REQUIRES_GROUP_PERMISSION(serverGroup, permission::i_server_group_needed_modify_power, permission::i_server_group_modify_power, true);
|
||||
|
||||
auto type = serverGroup->type();
|
||||
log::GroupType log_group_type;
|
||||
if(type == GroupType::GROUP_TYPE_QUERY) {
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_serverinstance_modify_querygroup, 1);
|
||||
log_group_type = log::GroupType::QUERY;
|
||||
} else if(type == GroupType::GROUP_TYPE_TEMPLATE) {
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_serverinstance_modify_templates, 1);
|
||||
log_group_type = log::GroupType::TEMPLATE;
|
||||
} else {
|
||||
log_group_type = log::GroupType::NORMAL;
|
||||
}
|
||||
|
||||
auto old_name = serverGroup->name();
|
||||
group_manager->renameGroup(serverGroup, cmd["name"].string());
|
||||
serverInstance->action_logger()->group_logger.log_group_rename(this->getServerId(), this->ref(), log::GroupTarget::SERVER, log_group_type, serverGroup->groupId(), serverGroup->name(), old_name);
|
||||
if(this->server)
|
||||
this->server->forEachClient([](shared_ptr<ConnectedClient> cl) {
|
||||
cl->notifyServerGroupList();
|
||||
@@ -456,18 +519,26 @@ command_result ConnectedClient::handleCommandServerGroupDel(Command &cmd) {
|
||||
|
||||
if(this->server && this->server->properties()[property::VIRTUALSERVER_DEFAULT_SERVER_GROUP] == serverGroup->groupId())
|
||||
return command_result{error::parameter_invalid, "Could not delete default server group!"};
|
||||
|
||||
if(serverInstance->properties()[property::SERVERINSTANCE_TEMPLATE_SERVERADMIN_GROUP] == serverGroup->groupId())
|
||||
return command_result{error::parameter_invalid, "Could not delete instance default server admin group!"};
|
||||
|
||||
if(serverInstance->properties()[property::SERVERINSTANCE_TEMPLATE_SERVERDEFAULT_GROUP] == serverGroup->groupId())
|
||||
return command_result{error::parameter_invalid, "Could not delete instance default server group!"};
|
||||
|
||||
if(serverInstance->properties()[property::SERVERINSTANCE_GUEST_SERVERQUERY_GROUP] == serverGroup->groupId())
|
||||
return command_result{error::parameter_invalid, "Could not delete instance default guest server query group!"};
|
||||
|
||||
auto type = serverGroup->type();
|
||||
log::GroupType log_group_type;
|
||||
if(type == GroupType::GROUP_TYPE_QUERY) {
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_serverinstance_modify_querygroup, 1);
|
||||
log_group_type = log::GroupType::QUERY;
|
||||
} else if(type == GroupType::GROUP_TYPE_TEMPLATE) {
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_serverinstance_modify_templates, 1);
|
||||
log_group_type = log::GroupType::TEMPLATE;
|
||||
} else {
|
||||
log_group_type = log::GroupType::NORMAL;
|
||||
}
|
||||
|
||||
if (!cmd["force"].as<bool>())
|
||||
@@ -475,6 +546,7 @@ command_result ConnectedClient::handleCommandServerGroupDel(Command &cmd) {
|
||||
return command_result{error::database_empty_result, "group not empty!"};
|
||||
|
||||
if (group_manager->deleteGroup(serverGroup)) {
|
||||
serverInstance->action_logger()->group_logger.log_group_delete(this->getServerId(), this->ref(), log::GroupTarget::SERVER, log_group_type, serverGroup->groupId(), serverGroup->name());
|
||||
if(this->server)
|
||||
this->server->forEachClient([&](shared_ptr<ConnectedClient> cl) {
|
||||
if(this->server->notifyClientPropertyUpdates(cl, this->server->groups->update_server_group_property(cl, true, cl->getChannel()))) {
|
||||
@@ -613,8 +685,10 @@ command_result ConnectedClient::handleCommandServerGroupAddClient(Command &cmd)
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<ConnectedClient> connected_client{};
|
||||
for(const auto& _server : target_server ? std::deque<shared_ptr<VirtualServer>>{target_server} : serverInstance->getVoiceServerManager()->serverInstances()) {
|
||||
for (const auto &targetClient : _server->findClientsByCldbId(target_cldbid)) {
|
||||
connected_client = targetClient;
|
||||
if (_server->notifyClientPropertyUpdates(targetClient, _server->groups->update_server_group_property(targetClient, true, targetClient->getChannel()))) {
|
||||
for (const auto &client : _server->getClients()) {
|
||||
if(client->isClientVisible(targetClient, true) || client == targetClient)
|
||||
@@ -627,6 +701,13 @@ command_result ConnectedClient::handleCommandServerGroupAddClient(Command &cmd)
|
||||
}
|
||||
}
|
||||
}
|
||||
for(const auto& group : applied_groups) {
|
||||
serverInstance->action_logger()->group_assignment_logger.log_group_assignment_add(target_server ? target_server->getServerId() : 0,
|
||||
this->ref(), log::GroupTarget::SERVER,
|
||||
group->groupId(), group->name(),
|
||||
target_cldbid, connected_client ? connected_client->getDisplayName() : ""
|
||||
);
|
||||
}
|
||||
|
||||
return command_result{error::ok};
|
||||
}
|
||||
@@ -740,8 +821,10 @@ command_result ConnectedClient::handleCommandServerGroupDelClient(Command &cmd)
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<ConnectedClient> connected_client{};
|
||||
for(const auto& _server : target_server ? std::deque<shared_ptr<VirtualServer>>{target_server} : serverInstance->getVoiceServerManager()->serverInstances()) {
|
||||
for (const auto &targetClient : _server->findClientsByCldbId(target_cldbid)) {
|
||||
connected_client = targetClient;
|
||||
ConnectedLockedClient clock{targetClient};
|
||||
if(!clock) continue;
|
||||
|
||||
@@ -757,6 +840,13 @@ command_result ConnectedClient::handleCommandServerGroupDelClient(Command &cmd)
|
||||
}
|
||||
}
|
||||
}
|
||||
for(const auto& group : applied_groups) {
|
||||
serverInstance->action_logger()->group_assignment_logger.log_group_assignment_remove(target_server ? target_server->getServerId() : 0,
|
||||
this->ref(), log::GroupTarget::SERVER,
|
||||
group->groupId(), group->name(),
|
||||
target_cldbid, connected_client ? connected_client->getDisplayName() : ""
|
||||
);
|
||||
}
|
||||
|
||||
return command_result{error::ok};
|
||||
}
|
||||
@@ -803,6 +893,15 @@ command_result ConnectedClient::handleCommandServerGroupAddPerm(Command &cmd) {
|
||||
auto permissions = serverGroup->permissions();
|
||||
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
|
||||
ppermission.apply_to(serverGroup->permissions(), permission::v2::PermissionUpdateType::set_value);
|
||||
ppermission.log_update(serverInstance->action_logger()->permission_logger,
|
||||
this->getServerId(),
|
||||
this->ref(),
|
||||
log::PermissionTarget::SERVER_GROUP,
|
||||
permission::v2::PermissionUpdateType::set_value,
|
||||
serverGroup->groupId(), serverGroup->name(),
|
||||
0, ""
|
||||
);
|
||||
|
||||
update_server_group_list |= ppermission.is_group_property();
|
||||
update_talk_power |= ppermission.is_client_view_property();
|
||||
}
|
||||
@@ -859,6 +958,15 @@ command_result ConnectedClient::handleCommandServerGroupDelPerm(Command &cmd) {
|
||||
bool update_talk_power{false}, update_server_group_list{false};
|
||||
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
|
||||
ppermission.apply_to(serverGroup->permissions(), permission::v2::PermissionUpdateType::delete_value);
|
||||
ppermission.log_update(serverInstance->action_logger()->permission_logger,
|
||||
this->getServerId(),
|
||||
this->ref(),
|
||||
log::PermissionTarget::SERVER_GROUP,
|
||||
permission::v2::PermissionUpdateType::delete_value,
|
||||
serverGroup->groupId(), serverGroup->name(),
|
||||
0, ""
|
||||
);
|
||||
|
||||
update_server_group_list |= ppermission.is_group_property();
|
||||
update_talk_power |= ppermission.is_client_view_property();
|
||||
}
|
||||
@@ -923,8 +1031,17 @@ command_result ConnectedClient::handleCommandServerGroupAutoAddPerm(ts::Command&
|
||||
|
||||
bool update_clients{false}, update_server_group_list{false};
|
||||
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
|
||||
for(const auto& serverGroup : groups)
|
||||
for(const auto& serverGroup : groups) {
|
||||
ppermission.apply_to(serverGroup->permissions(), permission::v2::PermissionUpdateType::set_value);
|
||||
ppermission.log_update(serverInstance->action_logger()->permission_logger,
|
||||
this->getServerId(),
|
||||
this->ref(),
|
||||
log::PermissionTarget::SERVER_GROUP,
|
||||
permission::v2::PermissionUpdateType::set_value,
|
||||
serverGroup->groupId(), serverGroup->name(),
|
||||
0, ""
|
||||
);
|
||||
}
|
||||
|
||||
update_server_group_list |= ppermission.is_group_property();
|
||||
update_clients |= ppermission.is_client_view_property();
|
||||
@@ -993,8 +1110,17 @@ command_result ConnectedClient::handleCommandServerGroupAutoDelPerm(ts::Command&
|
||||
|
||||
bool update_clients{false}, update_server_group_list{false};
|
||||
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
|
||||
for(const auto& serverGroup : groups)
|
||||
for(const auto& serverGroup : groups) {
|
||||
ppermission.apply_to(serverGroup->permissions(), permission::v2::PermissionUpdateType::delete_value);
|
||||
ppermission.log_update(serverInstance->action_logger()->permission_logger,
|
||||
this->getServerId(),
|
||||
this->ref(),
|
||||
log::PermissionTarget::SERVER_GROUP,
|
||||
permission::v2::PermissionUpdateType::delete_value,
|
||||
serverGroup->groupId(), serverGroup->name(),
|
||||
0, ""
|
||||
);
|
||||
}
|
||||
|
||||
update_server_group_list |= ppermission.is_group_property();
|
||||
update_clients |= ppermission.is_client_view_property();
|
||||
|
||||
Reference in New Issue
Block a user