Some more work for the new group manager
This commit is contained in:
@@ -57,6 +57,13 @@ void ConnectedClient::initialize_weak_reference(const std::shared_ptr<ConnectedC
|
||||
self->updateChannelClientProperties(true, true);
|
||||
}
|
||||
}};
|
||||
|
||||
this->task_update_displayed_groups = multi_shot_task{serverInstance->general_task_executor(), "update displayed groups for " + this->getLoggingPeerIp(), [weak_self]{
|
||||
auto self = weak_self.lock();
|
||||
if(self) {
|
||||
self->update_displayed_client_groups();
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
bool ConnectedClient::loadDataForCurrentServer() {
|
||||
@@ -1012,6 +1019,63 @@ bool ConnectedClient::update_client_needed_permissions() {
|
||||
return updated;
|
||||
}
|
||||
|
||||
void ConnectedClient::update_displayed_client_groups(bool& server_groups_changed, bool& channel_group_changed) {
|
||||
auto ref_server = this->server;
|
||||
auto group_manager = ref_server ? ref_server->group_manager() : serverInstance->group_manager();
|
||||
|
||||
GroupId channel_group_id{0};
|
||||
ChannelId channel_inherit_id{0};
|
||||
std::string server_group_assignments{};
|
||||
|
||||
{
|
||||
auto server_groups = group_manager->assignments().server_groups_of_client(groups::GroupAssignmentCalculateMode::GLOBAL, this->getClientDatabaseId());
|
||||
for(const auto& group_id : server_groups) {
|
||||
server_group_assignments += ",";
|
||||
server_group_assignments += std::to_string(group_id);
|
||||
}
|
||||
|
||||
if(!server_group_assignments.empty()) {
|
||||
server_group_assignments = server_group_assignments.substr(1);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
std::shared_ptr<BasicChannel> inherited_channel{this->currentChannel};
|
||||
auto channel_group = group_manager->assignments().calculate_channel_group_of_client(groups::GroupAssignmentCalculateMode::GLOBAL, this->getClientDatabaseId(), inherited_channel);
|
||||
if(channel_group.has_value()) {
|
||||
assert(inherited_channel);
|
||||
channel_group_id = *channel_group;
|
||||
channel_inherit_id = inherited_channel->channelId();
|
||||
} else {
|
||||
channel_group_id = 0;
|
||||
channel_inherit_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
server_groups_changed = false;
|
||||
channel_group_changed = false;
|
||||
|
||||
std::deque<property::ClientProperties> updated_properties{};
|
||||
if(this->properties()[property::CLIENT_SERVERGROUPS].update_value(server_group_assignments)) {
|
||||
updated_properties.push_back(property::CLIENT_SERVERGROUPS);
|
||||
server_groups_changed = true;
|
||||
}
|
||||
|
||||
if(this->properties()[property::CLIENT_CHANNEL_GROUP_ID].update_value(channel_group_id)) {
|
||||
updated_properties.push_back(property::CLIENT_CHANNEL_GROUP_ID);
|
||||
channel_group_changed = true;
|
||||
}
|
||||
|
||||
if(this->properties()[property::CLIENT_CHANNEL_GROUP_INHERITED_CHANNEL_ID].update_value(channel_inherit_id)) {
|
||||
updated_properties.push_back(property::CLIENT_CHANNEL_GROUP_ID);
|
||||
channel_group_changed = true;
|
||||
}
|
||||
|
||||
if(!updated_properties.empty() && ref_server) {
|
||||
ref_server->notifyClientPropertyUpdates(this->ref(), updated_properties);
|
||||
}
|
||||
}
|
||||
|
||||
void ConnectedClient::sendTSPermEditorWarning() {
|
||||
if(config::voice::warn_on_permission_editor) {
|
||||
if(system_clock::now() - this->command_times.servergrouplist > milliseconds(1000)) return;
|
||||
@@ -1192,11 +1256,7 @@ void ConnectedClient::useToken(token::TokenId token_id) {
|
||||
}
|
||||
|
||||
if(tree_registered && (server_groups_changed || channel_group_changed)) {
|
||||
/* TODO: Set "Update server groups" as task */
|
||||
auto updated_properties = this->getServer()->group_manager()->update_server_group_property(this->ref(), true, this->currentChannel);
|
||||
if(!updated_properties.empty()) {
|
||||
this->getServer()->notifyClientPropertyUpdates(this->ref(), updated_properties);
|
||||
}
|
||||
this->task_update_displayed_groups.enqueue();
|
||||
}
|
||||
|
||||
if(tree_registered && server_groups_changed) {
|
||||
|
||||
@@ -57,6 +57,12 @@ namespace ts {
|
||||
class WebClient;
|
||||
class MusicClient;
|
||||
|
||||
namespace groups {
|
||||
class Group;
|
||||
class ServerGroup;
|
||||
class ChannelGroup;
|
||||
}
|
||||
|
||||
struct ConnectionInfoData {
|
||||
std::chrono::time_point<std::chrono::system_clock> timestamp;
|
||||
std::map<std::string, std::string> properties;
|
||||
@@ -74,7 +80,6 @@ namespace ts {
|
||||
friend class DataClient;
|
||||
friend class SpeakingClient;
|
||||
friend class connection::VoiceClientConnection;
|
||||
friend class ts::GroupManager;
|
||||
friend class VirtualServerManager;
|
||||
public:
|
||||
explicit ConnectedClient(sql::SqlManager*, const std::shared_ptr<VirtualServer>& server);
|
||||
@@ -129,14 +134,15 @@ namespace ts {
|
||||
/** Notifies (after request) */
|
||||
bool sendNeededPermissions(bool /* force an update */); /* invoke this because it dosn't spam the client */
|
||||
virtual bool notifyClientNeededPermissions();
|
||||
virtual bool notifyServerGroupList(bool as_notify = true);
|
||||
virtual bool notifyGroupPermList(const std::shared_ptr<Group>&, bool);
|
||||
virtual bool notifyGroupPermList(const std::shared_ptr<groups::Group>&, bool);
|
||||
virtual bool notifyClientPermList(ClientDbId, const std::shared_ptr<permission::v2::PermissionManager>&, bool);
|
||||
virtual bool notifyChannelGroupList(bool as_notify = true);
|
||||
virtual bool notifyConnectionInfo(const std::shared_ptr<ConnectedClient> &target, const std::shared_ptr<ConnectionInfoData> &info);
|
||||
virtual bool notifyChannelSubscribed(const std::deque<std::shared_ptr<BasicChannel>> &);
|
||||
virtual bool notifyChannelUnsubscribed(const std::deque<std::shared_ptr<BasicChannel>> &);
|
||||
|
||||
virtual bool notifyServerGroupList(std::optional<ts::command_builder>& /* generated notify */, bool /* as notify */);
|
||||
virtual bool notifyChannelGroupList(std::optional<ts::command_builder>& /* generated notify */, bool /* as notify */);
|
||||
|
||||
/** Notifies (without request) */
|
||||
//Group server
|
||||
virtual bool notifyServerUpdated(std::shared_ptr<ConnectedClient>);
|
||||
@@ -299,6 +305,12 @@ namespace ts {
|
||||
*/
|
||||
bool update_client_needed_permissions();
|
||||
|
||||
/**
|
||||
* Attention: This method should never be called directly!
|
||||
* Use `task_update_displayed_groups` instead to schedule an update.
|
||||
*/
|
||||
void update_displayed_client_groups(bool& server_groups_changed, bool& channel_group_changed);
|
||||
|
||||
std::shared_lock<std::shared_mutex> require_connected_state(bool blocking = false) {
|
||||
//try_to_lock_t
|
||||
std::shared_lock<std::shared_mutex> disconnect_lock{};
|
||||
@@ -398,6 +410,7 @@ namespace ts {
|
||||
|
||||
multi_shot_task task_update_needed_permissions{};
|
||||
multi_shot_task task_update_channel_client_properties{};
|
||||
multi_shot_task task_update_displayed_groups{};
|
||||
|
||||
bool loadDataForCurrentServer() override;
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <misc/sassert.h>
|
||||
#include <log/LogUtils.h>
|
||||
#include "./web/WebClient.h"
|
||||
#include "../groups/GroupManager.h"
|
||||
|
||||
using namespace std::chrono;
|
||||
using namespace std;
|
||||
@@ -41,41 +42,83 @@ do { \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
bool ConnectedClient::notifyServerGroupList(bool as_notify) {
|
||||
Command cmd(as_notify ? "notifyservergrouplist" : "");
|
||||
int index = 0;
|
||||
template <typename T>
|
||||
inline void build_group_notify(ts::command_builder& notify, bool is_channel_groups, const std::vector<std::shared_ptr<T>>& available_groups) {
|
||||
std::string group_id_key{};
|
||||
permission::PermissionType permission_modify{};
|
||||
permission::PermissionType permission_add{};
|
||||
permission::PermissionType permission_remove{};
|
||||
|
||||
for (const auto& group : (this->server ? this->server->group_manager() : serverInstance->group_manager().get())->availableServerGroups(true)) {
|
||||
if(group->target() == GroupTarget::GROUPTARGET_CHANNEL) {
|
||||
cmd[index]["cgid"] = group->groupId();
|
||||
} else {
|
||||
cmd[index]["sgid"] = group->groupId();
|
||||
}
|
||||
for (const auto &prop : group->properties().list_properties(property::FLAG_GROUP_VIEW, this->getType() == CLIENT_TEAMSPEAK ? property::FLAG_NEW : (uint16_t) 0))
|
||||
cmd[index][std::string{prop.type().name}] = prop.value();
|
||||
if(is_channel_groups) {
|
||||
group_id_key = "cgid";
|
||||
|
||||
permission_modify = permission::i_channel_group_needed_modify_power;
|
||||
permission_add = permission::i_channel_group_needed_member_add_power;
|
||||
permission_remove = permission::i_channel_group_needed_member_remove_power;
|
||||
} else {
|
||||
group_id_key = "sgid";
|
||||
|
||||
auto modify_power = group->permissions()->permission_value_flagged(permission::i_displayed_group_needed_modify_power);
|
||||
auto add_power = group->permissions()->permission_value_flagged(permission::i_displayed_group_needed_member_add_power);
|
||||
auto remove_power = group->permissions()->permission_value_flagged(permission::i_displayed_group_needed_member_remove_power);
|
||||
cmd[index]["n_modifyp"] = modify_power.has_value ? modify_power.value : 0;
|
||||
cmd[index]["n_member_addp"] = add_power.has_value ? add_power.value : 0;
|
||||
cmd[index]["n_member_removep"] = remove_power.has_value ? remove_power.value : 0;
|
||||
index++;
|
||||
permission_modify = permission::i_server_group_needed_modify_power;
|
||||
permission_add = permission::i_server_group_needed_member_add_power;
|
||||
permission_remove = permission::i_server_group_needed_member_remove_power;
|
||||
}
|
||||
|
||||
this->sendCommand(cmd);
|
||||
size_t index{0};
|
||||
for(const auto& group : available_groups) {
|
||||
auto bulk = notify.bulk(index++);
|
||||
bulk.put_unchecked(group_id_key, group->group_id());
|
||||
bulk.put_unchecked("type", (uint8_t) group->group_type());
|
||||
bulk.put_unchecked("name", group->display_name());
|
||||
bulk.put_unchecked("sortid", group->sort_id());
|
||||
bulk.put_unchecked("savedb", group->save_assignments());
|
||||
bulk.put_unchecked("namemode", (uint8_t) group->name_mode());
|
||||
bulk.put_unchecked("iconid", group->icon_id());
|
||||
|
||||
auto modify_power = group->permissions()->permission_value_flagged(permission_modify);
|
||||
auto add_power = group->permissions()->permission_value_flagged(permission_add);
|
||||
auto remove_power = group->permissions()->permission_value_flagged(permission_remove);
|
||||
|
||||
bulk.put_unchecked("n_modifyp", modify_power.has_value ? modify_power.value : 0);
|
||||
bulk.put_unchecked("n_member_addp", add_power.has_value ? add_power.value : 0);
|
||||
bulk.put_unchecked("n_member_removep", remove_power.has_value ? remove_power.value : 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool ConnectedClient::notifyServerGroupList(std::optional<ts::command_builder> &generated_notify, bool as_notify) {
|
||||
if(!generated_notify.has_value()) {
|
||||
auto server_ref = this->server;
|
||||
auto group_manager = server_ref ? server_ref->group_manager() : serverInstance->group_manager();
|
||||
auto available_groups = group_manager->channel_groups()->available_groups(groups::GroupCalculateMode::GLOBAL);
|
||||
|
||||
build_group_notify(generated_notify.emplace(as_notify ? "notifyservergrouplist" : ""), false, available_groups);
|
||||
}
|
||||
|
||||
this->sendCommand(*generated_notify);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConnectedClient::notifyChannelGroupList(std::optional<ts::command_builder>& generated_notify, bool as_notify) {
|
||||
if(!generated_notify.has_value()) {
|
||||
auto server_ref = this->server;
|
||||
auto group_manager = server_ref ? server_ref->group_manager() : serverInstance->group_manager();
|
||||
auto available_groups = group_manager->channel_groups()->available_groups(groups::GroupCalculateMode::GLOBAL);
|
||||
|
||||
bool ConnectedClient::notifyGroupPermList(const std::shared_ptr<Group>& group, bool as_sid) {
|
||||
ts::command_builder result{this->getExternalType() == CLIENT_TEAMSPEAK ? group->target() == GROUPTARGET_SERVER ? "notifyservergrouppermlist" : "notifychannelgrouppermlist" : ""};
|
||||
build_group_notify(generated_notify.emplace(as_notify ? "notifychannelgrouplist" : ""), true, available_groups);
|
||||
}
|
||||
|
||||
if (group->target() == GROUPTARGET_SERVER)
|
||||
result.put_unchecked(0, "sgid", group->groupId());
|
||||
else
|
||||
result.put_unchecked(0, "cgid", group->groupId());
|
||||
this->sendCommand(*generated_notify);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConnectedClient::notifyGroupPermList(const std::shared_ptr<groups::Group>& group, bool as_sid) {
|
||||
auto is_channel_group = !!dynamic_pointer_cast<groups::ChannelGroup>(group);
|
||||
ts::command_builder result{this->notify_response_command(is_channel_group ? "notifychannelgrouppermlist" : "notifyservergrouppermlist")};
|
||||
|
||||
if (!is_channel_group) {
|
||||
result.put_unchecked(0, "sgid", group->group_id());
|
||||
} else {
|
||||
result.put_unchecked(0, "cgid", group->group_id());
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
|
||||
@@ -168,32 +211,6 @@ bool ConnectedClient::notifyClientPermList(ClientDbId cldbid, const std::shared_
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConnectedClient::notifyChannelGroupList(bool as_notify) {
|
||||
Command cmd(as_notify ? "notifychannelgrouplist" : "");
|
||||
int index = 0;
|
||||
for (const auto &group : (this->server ? this->server->group_manager() : serverInstance->group_manager().get())->availableChannelGroups(true)) {
|
||||
if(group->target() == GroupTarget::GROUPTARGET_CHANNEL) {
|
||||
cmd[index]["cgid"] = group->groupId();
|
||||
} else {
|
||||
cmd[index]["sgid"] = group->groupId();
|
||||
}
|
||||
for (auto &prop : group->properties().list_properties(property::FLAG_GROUP_VIEW, this->getType() == CLIENT_TEAMSPEAK ? property::FLAG_NEW : (uint16_t) 0))
|
||||
cmd[index][std::string{prop.type().name}] = prop.value();
|
||||
|
||||
|
||||
auto modify_power = group->permissions()->permission_value_flagged(permission::i_displayed_group_needed_modify_power);
|
||||
auto add_power = group->permissions()->permission_value_flagged(permission::i_displayed_group_needed_member_add_power);
|
||||
auto remove_power = group->permissions()->permission_value_flagged(permission::i_displayed_group_needed_member_remove_power);
|
||||
cmd[index]["n_modifyp"] = modify_power.has_value ? modify_power.value : 0;
|
||||
cmd[index]["n_member_addp"] = add_power.has_value ? add_power.value : 0;
|
||||
cmd[index]["n_member_removep"] = remove_power.has_value ? remove_power.value : 0;
|
||||
index++;
|
||||
}
|
||||
if(index == 0) return false;
|
||||
this->sendCommand(cmd);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConnectedClient::notifyTextMessage(ChatMessageMode mode, const shared_ptr<ConnectedClient> &invoker, uint64_t targetId, ChannelId channel_id, const std::chrono::system_clock::time_point& timestamp, const string &textMessage) {
|
||||
//notifytextmessage targetmode=1 msg=asdasd target=2 invokerid=1 invokername=WolverinDEV invokeruid=xxjnc14LmvTk+Lyrm8OOeo4tOqw=
|
||||
Command cmd("notifytextmessage");
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "./DataClient.h"
|
||||
#include "../InstanceHandler.h"
|
||||
#include "../groups/GroupManager.h"
|
||||
#include "../groups/GroupAssignmentManager.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace ts;
|
||||
@@ -196,22 +197,32 @@ std::vector<std::shared_ptr<groups::ServerGroup>> DataClient::assignedServerGrou
|
||||
}
|
||||
}
|
||||
|
||||
if(result.empty() && ref_server) {
|
||||
auto default_group_id = ref_server->properties()[property::VIRTUALSERVER_DEFAULT_SERVER_GROUP].as_or<GroupId>(0);
|
||||
auto default_group = group_manager->server_groups()->find_group(groups::GroupCalculateMode::GLOBAL, default_group_id);
|
||||
if(default_group) {
|
||||
result.push_back(default_group);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::shared_ptr<groups::ChannelGroup> DataClient::assignedChannelGroup(const shared_ptr<BasicChannel> &channel) {
|
||||
std::shared_ptr<groups::ChannelGroup> DataClient::assignedChannelGroup(const std::shared_ptr<BasicChannel> &channel) {
|
||||
auto ref_server = this->server;
|
||||
assert(channel);
|
||||
if(!channel || !ref_server) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<groups::ChannelGroup> result{};
|
||||
std::shared_ptr<BasicChannel> inherited_channel{channel};
|
||||
|
||||
auto group_manager = ref_server ? ref_server->group_manager() : serverInstance->group_manager();
|
||||
auto channel_group_assignment = group_manager->assignments().channel_group_of_client(groups::GroupAssignmentCalculateMode::GLOBAL, this->getClientDatabaseId(), channel->channelId());
|
||||
if(channel_group_assignment.has_value()) {
|
||||
result = group_manager->channel_groups()->find_group(groups::GroupCalculateMode::GLOBAL, channel_group_assignment->group_id);
|
||||
auto assigned_group_id = group_manager->assignments().calculate_channel_group_of_client(groups::GroupAssignmentCalculateMode::GLOBAL, this->getClientDatabaseId(), inherited_channel);
|
||||
|
||||
std::shared_ptr<groups::ChannelGroup> result{};
|
||||
if(assigned_group_id.has_value()) {
|
||||
result = group_manager->channel_groups()->find_group(groups::GroupCalculateMode::GLOBAL, *assigned_group_id);
|
||||
}
|
||||
|
||||
if(!result) {
|
||||
|
||||
@@ -517,8 +517,14 @@ void SpeakingClient::processJoin() {
|
||||
TIMING_STEP(timings, "join move ");
|
||||
|
||||
this->properties()->triggerAllModified();
|
||||
this->notifyServerGroupList();
|
||||
this->notifyChannelGroupList();
|
||||
{
|
||||
std::optional<ts::command_builder> generated_notify{};
|
||||
this->notifyServerGroupList(generated_notify, true);
|
||||
}
|
||||
{
|
||||
std::optional<ts::command_builder> generated_notify{};
|
||||
this->notifyChannelGroupList(generated_notify, true);
|
||||
}
|
||||
TIMING_STEP(timings, "notify grou");
|
||||
logMessage(this->getServerId(), "Voice client {}/{} ({}) from {} joined.",
|
||||
this->getClientDatabaseId(),
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "../../manager/PermissionNameMapper.h"
|
||||
#include "../../server/QueryServer.h"
|
||||
#include "../../server/VoiceServer.h"
|
||||
#include "../../groups/GroupManager.h"
|
||||
#include "../ConnectedClient.h"
|
||||
#include "../InternalClient.h"
|
||||
#include "../music/MusicClient.h"
|
||||
@@ -137,58 +138,63 @@ command_result ConnectedClient::handleCommandChannelGroupAdd(Command &cmd) {
|
||||
CMD_CHK_AND_INC_FLOOD_POINTS(5);
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_channelgroup_create, 1);
|
||||
|
||||
auto group_manager = this->server ? this->server->group_manager() : serverInstance->group_manager().get();
|
||||
auto group_manager = this->server ? this->server->group_manager() : serverInstance->group_manager();
|
||||
|
||||
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!"};
|
||||
}
|
||||
auto group_type = cmd["type"].as<groups::GroupType>();
|
||||
switch (group_type) {
|
||||
case groups::GroupType::GROUP_TYPE_QUERY:
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_serverinstance_modify_querygroup, 1);
|
||||
log_group_type = log::GroupType::QUERY;
|
||||
break;
|
||||
|
||||
log_group_type = log::GroupType::NORMAL;
|
||||
case groups::GroupType::GROUP_TYPE_TEMPLATE:
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_serverinstance_modify_templates, 1);
|
||||
log_group_type = log::GroupType::TEMPLATE;
|
||||
break;
|
||||
|
||||
case groups::GroupType::GROUP_TYPE_NORMAL:
|
||||
if (!this->server) {
|
||||
return command_result{error::parameter_invalid, "you cant create normal groups on the template server!"};
|
||||
}
|
||||
log_group_type = log::GroupType::NORMAL;
|
||||
break;
|
||||
|
||||
case groups::GroupType::GROUP_TYPE_UNKNOWN:
|
||||
default:
|
||||
return command_result{error::parameter_invalid, "type"};
|
||||
}
|
||||
|
||||
if (cmd["name"].string().empty()) {
|
||||
return command_result{error::parameter_invalid, "invalid group name"};
|
||||
}
|
||||
std::shared_ptr<groups::ChannelGroup> group{};
|
||||
auto result = group_manager->channel_groups()->create_group(group_type, cmd["name"].string(), group);
|
||||
switch(result) {
|
||||
case groups::GroupCreateResult::SUCCESS:
|
||||
break;
|
||||
|
||||
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"};
|
||||
}
|
||||
}
|
||||
case groups::GroupCreateResult::NAME_TOO_SHORT:
|
||||
case groups::GroupCreateResult::NAME_TOO_LONG:
|
||||
return command_result{error::parameter_invalid, "name"};
|
||||
|
||||
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, "");
|
||||
case groups::GroupCreateResult::NAME_ALREADY_IN_USED:
|
||||
return command_result{error::group_name_inuse};
|
||||
|
||||
case groups::GroupCreateResult::DATABASE_ERROR:
|
||||
default:
|
||||
return command_result{error::vs_critical};
|
||||
}
|
||||
assert(group);
|
||||
serverInstance->action_logger()->group_logger.log_group_create(this->getServerId(), this->ref(), log::GroupTarget::CHANNEL, log_group_type, group->group_id(), group->display_name(), 0, "");
|
||||
|
||||
{
|
||||
ts::command_builder notify{this->notify_response_command("notifychannelgroupadded")};
|
||||
notify.put_unchecked(0, "cgid", group->groupId());
|
||||
notify.put_unchecked(0, "cgid", group->group_id());
|
||||
this->sendCommand(notify);
|
||||
}
|
||||
|
||||
if (group) {
|
||||
group->permissions()->set_permission(permission::b_group_is_permanent, {1, 0}, permission::v2::set_value, permission::v2::do_nothing);
|
||||
if (this->server) {
|
||||
if (this->getType() == ClientType::CLIENT_QUERY) {
|
||||
this->server->forEachClient([&](const std::shared_ptr<ConnectedClient> &cl) {
|
||||
if (cl == this) {
|
||||
return;
|
||||
}
|
||||
|
||||
cl->notifyChannelGroupList();
|
||||
});
|
||||
} else {
|
||||
this->server->forEachClient([](const std::shared_ptr<ConnectedClient> &cl) {
|
||||
cl->notifyChannelGroupList();
|
||||
});
|
||||
}
|
||||
this->server->enqueue_notify_channel_group_list();
|
||||
}
|
||||
} else {
|
||||
return command_result{error::group_invalid_id};
|
||||
@@ -200,30 +206,40 @@ command_result ConnectedClient::handleCommandChannelGroupAdd(Command &cmd) {
|
||||
command_result ConnectedClient::handleCommandChannelGroupCopy(Command &cmd) {
|
||||
CMD_RESET_IDLE;
|
||||
CMD_CHK_AND_INC_FLOOD_POINTS(5);
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_channelgroup_create, 1);
|
||||
|
||||
auto ref_server = this->server;
|
||||
|
||||
auto group_manager = this->server ? this->server->group_manager() : serverInstance->group_manager().get();
|
||||
auto group_manager = this->server ? this->server->group_manager() : serverInstance->group_manager();
|
||||
|
||||
auto source_group_id = cmd["scgid"].as<GroupId>();
|
||||
auto source_group = group_manager->findGroup(source_group_id);
|
||||
auto source_group = group_manager->channel_groups()->find_group(groups::GroupCalculateMode::GLOBAL, source_group_id);
|
||||
|
||||
if (!source_group || source_group->target() != GROUPTARGET_CHANNEL)
|
||||
return command_result{error::group_invalid_id, "invalid source group"};
|
||||
if (!source_group) {
|
||||
return command_result{error::group_invalid_id, "invalid source group id"};
|
||||
}
|
||||
|
||||
const auto group_type_modificable = [&](GroupType type) {
|
||||
const auto group_type_modifiable = [&](groups::GroupType type) {
|
||||
switch (type) {
|
||||
case GroupType::GROUP_TYPE_TEMPLATE:
|
||||
if (!permission::v2::permission_granted(1, this->calculate_permission(permission::b_serverinstance_modify_templates, 0)))
|
||||
case groups::GroupType::GROUP_TYPE_TEMPLATE:
|
||||
if (!permission::v2::permission_granted(1, this->calculate_permission(permission::b_serverinstance_modify_templates, 0))) {
|
||||
return permission::b_serverinstance_modify_templates;
|
||||
}
|
||||
|
||||
break;
|
||||
case GroupType::GROUP_TYPE_QUERY:
|
||||
if (!permission::v2::permission_granted(1, this->calculate_permission(permission::b_serverinstance_modify_querygroup, 0)))
|
||||
case groups::GroupType::GROUP_TYPE_QUERY:
|
||||
if (!permission::v2::permission_granted(1, this->calculate_permission(permission::b_serverinstance_modify_querygroup, 0))) {
|
||||
return permission::b_serverinstance_modify_querygroup;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case GroupType::GROUP_TYPE_NORMAL:
|
||||
case groups::GroupType::GROUP_TYPE_NORMAL:
|
||||
if (!permission::v2::permission_granted(1, this->calculate_permission(permission::b_virtualserver_channelgroup_create, 0))) {
|
||||
return permission::b_virtualserver_channelgroup_create;
|
||||
}
|
||||
break;
|
||||
|
||||
case groups::GroupType::GROUP_TYPE_UNKNOWN:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -231,107 +247,149 @@ command_result ConnectedClient::handleCommandChannelGroupCopy(Command &cmd) {
|
||||
};
|
||||
|
||||
{
|
||||
auto result = group_type_modificable(source_group->type());
|
||||
if (result != permission::undefined)
|
||||
auto result = group_type_modifiable(source_group->group_type());
|
||||
if (result != permission::undefined) {
|
||||
return command_result{result};
|
||||
}
|
||||
}
|
||||
|
||||
auto global_update = false;
|
||||
if (cmd[0].has("tcgid") && cmd["tcgid"].as<GroupId>() != 0) {
|
||||
//Copy an existing group
|
||||
auto target_group = group_manager->findGroup(cmd["tcgid"]);
|
||||
if (!target_group || target_group->target() != GROUPTARGET_CHANNEL)
|
||||
auto target_group_id = cmd["tcgid"].as<GroupId>();
|
||||
auto target_group = group_manager->channel_groups()->find_group(groups::GroupCalculateMode::GLOBAL, target_group_id);
|
||||
if (!target_group) {
|
||||
return command_result{error::group_invalid_id, "invalid target group"};
|
||||
|
||||
{
|
||||
auto result = group_type_modificable(target_group->type());
|
||||
if (result != permission::undefined)
|
||||
return command_result{result};
|
||||
}
|
||||
|
||||
if (!target_group->permission_granted(permission::i_channel_group_needed_modify_power, this->calculate_permission(permission::i_channel_group_modify_power, 0), true))
|
||||
return command_result{permission::i_channel_group_modify_power};
|
||||
if(!target_group->permission_granted(permission::i_channel_group_needed_modify_power, this->calculate_permission(permission::i_channel_group_modify_power, 0), true)) {
|
||||
return ts::command_result{permission::i_channel_group_needed_modify_power};
|
||||
}
|
||||
|
||||
if (!group_manager->copyGroupPermissions(source_group, target_group))
|
||||
return command_result{error::vs_critical, "failed to copy group permissions"};
|
||||
{
|
||||
auto result = group_type_modifiable(target_group->group_type());
|
||||
if (result != permission::undefined) {
|
||||
return command_result{result};
|
||||
}
|
||||
}
|
||||
|
||||
auto result = group_manager->channel_groups()->copy_group_permissions(source_group_id, target_group_id);
|
||||
switch(result) {
|
||||
case groups::GroupCopyResult::SUCCESS:
|
||||
break;
|
||||
|
||||
case groups::GroupCopyResult::UNKNOWN_SOURCE_GROUP:
|
||||
return command_result{error::vs_critical, "internal unknown source group"};
|
||||
|
||||
case groups::GroupCopyResult::UNKNOWN_TARGET_GROUP:
|
||||
return command_result{error::vs_critical, "internal unknown target group"};
|
||||
|
||||
case groups::GroupCopyResult::DATABASE_ERROR:
|
||||
return command_result{error::vs_critical, "database error"};
|
||||
|
||||
case groups::GroupCopyResult::NAME_ALREADY_IN_USE:
|
||||
return command_result{error::group_name_inuse};
|
||||
|
||||
default:
|
||||
return command_result{error::vs_critical};
|
||||
}
|
||||
|
||||
log::GroupType log_group_type;
|
||||
switch (target_group->type()) {
|
||||
case GroupType::GROUP_TYPE_QUERY:
|
||||
switch (target_group->group_type()) {
|
||||
case groups::GroupType::GROUP_TYPE_QUERY:
|
||||
log_group_type = log::GroupType::QUERY;
|
||||
break;
|
||||
|
||||
case GroupType::GROUP_TYPE_TEMPLATE:
|
||||
case groups::GroupType::GROUP_TYPE_TEMPLATE:
|
||||
log_group_type = log::GroupType::TEMPLATE;
|
||||
break;
|
||||
|
||||
case GroupType::GROUP_TYPE_NORMAL:
|
||||
case groups::GroupType::GROUP_TYPE_NORMAL:
|
||||
case groups::GroupType::GROUP_TYPE_UNKNOWN:
|
||||
default:
|
||||
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());
|
||||
serverInstance->action_logger()->group_logger.log_group_permission_copy(target_group->group_type() != groups::GroupType::GROUP_TYPE_NORMAL ? 0 : this->getServerId(),
|
||||
this->ref(), log::GroupTarget::CHANNEL, log_group_type, target_group->group_id(), target_group->display_name(), source_group->group_id(), source_group->display_name());
|
||||
|
||||
|
||||
global_update = !this->server || !group_manager->isLocalGroup(target_group);
|
||||
global_update = !this->server || !group_manager->channel_groups()->find_group(groups::GroupCalculateMode::LOCAL, target_group_id);
|
||||
} else {
|
||||
//Copy a new group
|
||||
auto target_type = cmd["type"].as<GroupType>();
|
||||
|
||||
{
|
||||
auto result = group_type_modificable(target_type);
|
||||
if (result != permission::undefined)
|
||||
return command_result{result};
|
||||
}
|
||||
auto target_type = cmd["type"].as<groups::GroupType>();
|
||||
|
||||
log::GroupType log_group_type;
|
||||
switch (target_type) {
|
||||
case GroupType::GROUP_TYPE_QUERY:
|
||||
case groups::GroupType::GROUP_TYPE_QUERY:
|
||||
log_group_type = log::GroupType::QUERY;
|
||||
break;
|
||||
|
||||
case GroupType::GROUP_TYPE_TEMPLATE:
|
||||
case groups::GroupType::GROUP_TYPE_TEMPLATE:
|
||||
log_group_type = log::GroupType::TEMPLATE;
|
||||
break;
|
||||
|
||||
case GroupType::GROUP_TYPE_NORMAL:
|
||||
case groups::GroupType::GROUP_TYPE_NORMAL:
|
||||
log_group_type = log::GroupType::NORMAL;
|
||||
break;
|
||||
|
||||
case groups::GroupType::GROUP_TYPE_UNKNOWN:
|
||||
default:
|
||||
return command_result{error::parameter_invalid, "type"};
|
||||
}
|
||||
|
||||
if (!ref_server && target_type == GroupType::GROUP_TYPE_NORMAL)
|
||||
{
|
||||
auto result = group_type_modifiable(target_type);
|
||||
if (result != permission::undefined) {
|
||||
return command_result{result};
|
||||
}
|
||||
}
|
||||
|
||||
if (!ref_server && target_type == groups::GroupType::GROUP_TYPE_NORMAL) {
|
||||
return command_result{error::parameter_invalid, "You cant create normal groups on the template server!"};
|
||||
}
|
||||
|
||||
if (!group_manager->findGroup(GroupTarget::GROUPTARGET_CHANNEL, cmd["name"].string()).empty())
|
||||
return command_result{error::group_name_inuse, "You cant create normal groups on the template server!"};
|
||||
std::shared_ptr<groups::ChannelGroup> created_group{};
|
||||
auto result = group_manager->channel_groups()->copy_group(source_group_id, target_type, cmd["name"].string(), created_group);
|
||||
switch(result) {
|
||||
case groups::GroupCopyResult::SUCCESS:
|
||||
break;
|
||||
|
||||
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());
|
||||
case groups::GroupCopyResult::UNKNOWN_SOURCE_GROUP:
|
||||
return command_result{error::vs_critical, "internal unknown source group"};
|
||||
|
||||
if (this->getType() == ClientType::CLIENT_QUERY) {
|
||||
Command notify("");
|
||||
notify["cgid"] = target_group_id;
|
||||
case groups::GroupCopyResult::UNKNOWN_TARGET_GROUP:
|
||||
return command_result{error::vs_critical, "internal unknown target group"};
|
||||
|
||||
case groups::GroupCopyResult::DATABASE_ERROR:
|
||||
return command_result{error::vs_critical, "database error"};
|
||||
|
||||
case groups::GroupCopyResult::NAME_ALREADY_IN_USE:
|
||||
return command_result{error::group_name_inuse};
|
||||
|
||||
default:
|
||||
return command_result{error::vs_critical};
|
||||
}
|
||||
|
||||
assert(created_group);
|
||||
serverInstance->action_logger()->group_logger.log_group_create(target_type != groups::GroupType::GROUP_TYPE_NORMAL ? 0 : this->getServerId(),
|
||||
this->ref(), log::GroupTarget::CHANNEL, log_group_type, created_group->group_id(), cmd["name"], source_group->group_id(), source_group->display_name());
|
||||
|
||||
{
|
||||
ts::command_builder notify{this->notify_response_command("notifychannelgroupcopied")};
|
||||
notify.put_unchecked(0, "cgid", created_group->group_id());
|
||||
this->sendCommand(notify);
|
||||
}
|
||||
|
||||
global_update = !this->server || !group_manager->isLocalGroup(group_manager->findGroup(target_group_id));
|
||||
global_update = !this->server;
|
||||
}
|
||||
|
||||
for (const auto &server : (global_update ? serverInstance->getVoiceServerManager()->serverInstances() : deque<shared_ptr<VirtualServer>>{this->server}))
|
||||
if (server)
|
||||
server->forEachClient([](shared_ptr<ConnectedClient> cl) {
|
||||
cl->notifyChannelGroupList();
|
||||
});
|
||||
for (const auto &server : (global_update ? serverInstance->getVoiceServerManager()->serverInstances() : deque<shared_ptr<VirtualServer>>{this->server})) {
|
||||
if (server) {
|
||||
server->enqueue_notify_channel_group_list();
|
||||
}
|
||||
}
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
@@ -339,32 +397,50 @@ command_result ConnectedClient::handleCommandChannelGroupRename(Command &cmd) {
|
||||
CMD_RESET_IDLE;
|
||||
CMD_CHK_AND_INC_FLOOD_POINTS(5);
|
||||
|
||||
auto group_manager = this->server ? this->server->group_manager() : serverInstance->group_manager().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"};
|
||||
auto group_manager = this->server ? this->server->group_manager() : serverInstance->group_manager();
|
||||
auto channel_group = group_manager->channel_groups()->find_group(groups::GroupCalculateMode::GLOBAL, cmd["cgid"].as<GroupId>());
|
||||
if (!channel_group) {
|
||||
return command_result{error::group_invalid_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();
|
||||
auto type = channel_group->group_type();
|
||||
log::GroupType log_group_type;
|
||||
if (type == GroupType::GROUP_TYPE_QUERY) {
|
||||
if (type == groups::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) {
|
||||
} else if (type == groups::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);
|
||||
auto old_name = channel_group->display_name();
|
||||
auto result = group_manager->channel_groups()->rename_group(channel_group->group_id(), cmd["name"].string());
|
||||
switch(result) {
|
||||
case groups::GroupRenameResult::SUCCESS:
|
||||
break;
|
||||
|
||||
if (this->server)
|
||||
this->server->forEachClient([](shared_ptr<ConnectedClient> cl) {
|
||||
cl->notifyChannelGroupList();
|
||||
});
|
||||
case groups::GroupRenameResult::INVALID_GROUP_ID:
|
||||
return ts::command_result{error::vs_critical, "internal invalid group id"};
|
||||
|
||||
case groups::GroupRenameResult::NAME_INVALID:
|
||||
return ts::command_result{error::parameter_invalid, "name"};
|
||||
|
||||
case groups::GroupRenameResult::NAME_ALREADY_USED:
|
||||
return ts::command_result{error::group_name_inuse};
|
||||
|
||||
case groups::GroupRenameResult::DATABASE_ERROR:
|
||||
default:
|
||||
return ts::command_result{error::vs_critical};
|
||||
}
|
||||
|
||||
serverInstance->action_logger()->group_logger.log_group_rename(this->getServerId(), this->ref(), log::GroupTarget::CHANNEL, log_group_type, channel_group->group_id(), channel_group->display_name(), old_name);
|
||||
if (this->server) {
|
||||
this->server->enqueue_notify_channel_group_list();
|
||||
}
|
||||
|
||||
return command_result{error::ok};
|
||||
}
|
||||
@@ -372,54 +448,101 @@ command_result ConnectedClient::handleCommandChannelGroupRename(Command &cmd) {
|
||||
command_result ConnectedClient::handleCommandChannelGroupDel(Command &cmd) {
|
||||
CMD_RESET_IDLE;
|
||||
CMD_CHK_AND_INC_FLOOD_POINTS(5);
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_channelgroup_delete, 1);
|
||||
|
||||
auto group_manager = this->server ? this->server->group_manager() : serverInstance->group_manager().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"};
|
||||
auto ref_server = this->server;
|
||||
auto group_manager = ref_server ? ref_server->group_manager() : serverInstance->group_manager();
|
||||
auto channel_group = group_manager->channel_groups()->find_group(groups::GroupCalculateMode::GLOBAL, cmd["cgid"].as<GroupId>());
|
||||
if (!channel_group) {
|
||||
return command_result{error::group_invalid_id};
|
||||
}
|
||||
|
||||
if(!channel_group->permission_granted(permission::i_channel_group_needed_modify_power, this->calculate_permission(permission::i_channel_group_modify_power, 0), true)) {
|
||||
return command_result{permission::i_channel_group_needed_modify_power};
|
||||
}
|
||||
|
||||
if (this->server) {
|
||||
if (this->server->properties()[property::VIRTUALSERVER_DEFAULT_CHANNEL_GROUP] == channel_group->groupId())
|
||||
if (this->server->properties()[property::VIRTUALSERVER_DEFAULT_CHANNEL_GROUP] == channel_group->group_id()) {
|
||||
return command_result{error::parameter_invalid, "Could not delete default channel group!"};
|
||||
if (this->server->properties()[property::VIRTUALSERVER_DEFAULT_CHANNEL_ADMIN_GROUP] == channel_group->groupId())
|
||||
}
|
||||
if (this->server->properties()[property::VIRTUALSERVER_DEFAULT_CHANNEL_ADMIN_GROUP] == channel_group->group_id()) {
|
||||
return command_result{error::parameter_invalid, "Could not delete default channel admin group!"};
|
||||
}
|
||||
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)) {
|
||||
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->group_manager()->update_server_group_property(cl, true, cl->getChannel()))) {
|
||||
cl->task_update_needed_permissions.enqueue();
|
||||
}
|
||||
cl->notifyChannelGroupList();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if(this->server) {
|
||||
this->server->tokenManager->handle_channel_group_deleted(channel_group->groupId());
|
||||
if (serverInstance->properties()[property::SERVERINSTANCE_TEMPLATE_CHANNELDEFAULT_GROUP] == channel_group->group_id()) {
|
||||
return command_result{error::parameter_invalid, "Could not delete instance default channel group!"};
|
||||
}
|
||||
|
||||
if (serverInstance->properties()[property::SERVERINSTANCE_TEMPLATE_CHANNELADMIN_GROUP] == channel_group->group_id()) {
|
||||
return command_result{error::parameter_invalid, "Could not delete instance default channel admin group!"};
|
||||
}
|
||||
|
||||
log::GroupType log_group_type;
|
||||
switch (channel_group->group_type()) {
|
||||
case groups::GroupType::GROUP_TYPE_QUERY:
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_serverinstance_modify_querygroup, 1);
|
||||
log_group_type = log::GroupType::QUERY;
|
||||
break;
|
||||
|
||||
case groups::GroupType::GROUP_TYPE_TEMPLATE:
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_serverinstance_modify_templates, 1);
|
||||
log_group_type = log::GroupType::TEMPLATE;
|
||||
break;
|
||||
|
||||
case groups::GroupType::GROUP_TYPE_NORMAL:
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_channelgroup_delete, 1);
|
||||
log_group_type = log::GroupType::NORMAL;
|
||||
break;
|
||||
|
||||
case groups::GroupType::GROUP_TYPE_UNKNOWN:
|
||||
default:
|
||||
return ts::command_result{error::vs_critical};
|
||||
}
|
||||
|
||||
if (!cmd["force"].as<bool>()) {
|
||||
if(!group_manager->assignments().is_channel_group_empty(channel_group->group_id())) {
|
||||
return command_result{error::group_not_empty};
|
||||
}
|
||||
}
|
||||
|
||||
auto result = group_manager->channel_groups()->delete_group(channel_group->group_id());
|
||||
switch(result) {
|
||||
case groups::GroupDeleteResult::SUCCESS:
|
||||
break;
|
||||
|
||||
case groups::GroupDeleteResult::INVALID_GROUP_ID:
|
||||
case groups::GroupDeleteResult::DATABASE_ERROR:
|
||||
default:
|
||||
return ts::command_result{error::vs_critical};
|
||||
}
|
||||
|
||||
serverInstance->action_logger()->group_logger.log_group_delete(this->getServerId(), this->ref(), log::GroupTarget::SERVER, log_group_type, channel_group->group_id(), channel_group->display_name());
|
||||
if(ref_server) {
|
||||
auto channel_group_id = channel_group->group_id();
|
||||
|
||||
std::deque<std::shared_ptr<ConnectedClient>> affected_clients{};
|
||||
this->server->forEachClient([&](std::shared_ptr<ConnectedClient> client) {
|
||||
/* TODO: It might be faster to query all clients of the group and search within that list only */
|
||||
auto assigned_group = group_manager->assignments().exact_channel_group_of_client(groups::GroupAssignmentCalculateMode::GLOBAL, client->getClientDatabaseId(), client->getChannelId());
|
||||
if(assigned_group.has_value() && assigned_group->group_id == channel_group_id) {
|
||||
affected_clients.push_back(client);
|
||||
}
|
||||
});
|
||||
|
||||
ref_server->enqueue_notify_channel_group_list();
|
||||
ref_server->group_manager()->assignments().handle_channel_group_deleted(channel_group_id);
|
||||
|
||||
for(const auto& client : affected_clients) {
|
||||
/*
|
||||
* Now we can enqueue all the updates since handle_channel_group_deleted has already been called.
|
||||
* If not done in that order, the group might already got updated before we actiually deleted it from the group manager.
|
||||
*/
|
||||
client->task_update_displayed_groups.enqueue();
|
||||
client->task_update_needed_permissions.enqueue();
|
||||
client->task_update_channel_client_properties.enqueue();
|
||||
}
|
||||
|
||||
ref_server->tokenManager->handle_channel_group_deleted(channel_group_id);
|
||||
}
|
||||
|
||||
return command_result{error::ok};
|
||||
@@ -430,7 +553,9 @@ command_result ConnectedClient::handleCommandChannelGroupList(Command &) {
|
||||
CMD_CHK_AND_INC_FLOOD_POINTS(5);
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_channelgroup_list, 1);
|
||||
|
||||
this->notifyChannelGroupList(this->getType() != ClientType::CLIENT_QUERY);
|
||||
std::optional<ts::command_builder> notify{};
|
||||
this->notifyChannelGroupList(notify, this->getType() != ClientType::CLIENT_QUERY);
|
||||
|
||||
this->command_times.servergrouplist = system_clock::now();
|
||||
return command_result{error::ok};
|
||||
}
|
||||
@@ -439,69 +564,29 @@ command_result ConnectedClient::handleCommandChannelGroupClientList(Command &cmd
|
||||
CMD_REQ_SERVER;
|
||||
CMD_RESET_IDLE;
|
||||
CMD_CHK_AND_INC_FLOOD_POINTS(5);
|
||||
|
||||
auto target_channel_id = cmd[0].has("cid") ? cmd["cid"].as<ChannelId>() : 0;
|
||||
if (target_channel_id > 0) {
|
||||
ACTION_REQUIRES_PERMISSION(permission::b_virtualserver_channelgroup_client_list, 1, target_channel_id);
|
||||
} else {
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_channelgroup_client_list, 1);
|
||||
}
|
||||
Command result(this->getExternalType() == ClientType::CLIENT_TEAMSPEAK ? "notifychannelgroupclientlist" : "");
|
||||
auto target_client_database_id = cmd[0].has("cldbid") ? cmd["cldbid"].as<ClientDbId>() : 0;
|
||||
auto target_group_id = cmd[0].has("cgid") ? cmd["cgid"].as<GroupId>() : 0;
|
||||
|
||||
deque<variable> variables{variable{":sid", this->getServerId()}};
|
||||
string query = "SELECT `groupId`, `cldbid`, `until`, `channelId` FROM `assignedGroups` WHERE `serverId` = :sid";
|
||||
ACTION_REQUIRES_PERMISSION(permission::b_virtualserver_channelgroup_client_list, 1, target_channel_id);
|
||||
|
||||
if (cmd[0].has("cgid") && cmd["cgid"].as<GroupId>() > 0) {
|
||||
auto group = this->server->group_manager()->findGroup(cmd["cgid"]);
|
||||
if (!group || group->target() != GroupTarget::GROUPTARGET_CHANNEL)
|
||||
return command_result{error::parameter_invalid, "invalid channel group id"};
|
||||
query += " AND `groupId` = :groupId";
|
||||
variables.push_back({":groupId", cmd["cgid"].as<GroupId>()});
|
||||
} else {
|
||||
query += " AND `groupId` IN (SELECT `groupId` FROM `groups` WHERE `serverId` = :sid AND `target` = :target)";
|
||||
variables.push_back({":target", GroupTarget::GROUPTARGET_CHANNEL});
|
||||
auto result = this->server->group_manager()->assignments().channel_group_list(target_group_id, target_channel_id, target_client_database_id);
|
||||
if(result.empty()) {
|
||||
return ts::command_result{error::database_empty_result};
|
||||
}
|
||||
if (cmd[0].has("cldbid") && cmd["cldbid"].as<ClientDbId>() > 0) {
|
||||
query += " AND `cldbid` = :cldbid";
|
||||
variables.push_back({":cldbid", cmd["cldbid"].as<ClientDbId>()});
|
||||
}
|
||||
if (cmd[0].has("cid") && cmd["cid"].as<ChannelId>() > 0) {
|
||||
auto channel = this->server->getChannelTree()->findChannel(cmd["cid"]);
|
||||
if (!channel)
|
||||
return command_result{error::parameter_invalid, "invalid channel id"};
|
||||
query += " AND `channelId` = :cid";
|
||||
variables.push_back({":cid", cmd["cid"].as<ChannelId>()});
|
||||
}
|
||||
debugMessage(this->getServerId(), "Command channelgroupclientlist sql: {}", query);
|
||||
|
||||
auto command = sql::command(this->sql, query);
|
||||
for (const auto &variable : variables)
|
||||
command.value(variable);
|
||||
|
||||
int index = 0;
|
||||
command.query([&](Command &command, int &index, int length, string *values, string *names) {
|
||||
GroupId group_id = 0;
|
||||
ChannelId channel_id = 0;
|
||||
ClientDbId cldbid = 0;
|
||||
for (int i = 0; i < length; i++) {
|
||||
try {
|
||||
if (names[i] == "groupId")
|
||||
group_id = stoll(values[i]);
|
||||
else if (names[i] == "cldbid")
|
||||
cldbid = stoll(values[i]);
|
||||
else if (names[i] == "channelId")
|
||||
channel_id = stoll(values[i]);
|
||||
} catch (std::exception &ex) {
|
||||
logError(this->getServerId(), "Failed to parse db field {}", names[i]);
|
||||
}
|
||||
}
|
||||
result[index]["cid"] = channel_id;
|
||||
result[index]["cgid"] = group_id;
|
||||
result[index]["cldbid"] = cldbid;
|
||||
index++;
|
||||
},
|
||||
result, index);
|
||||
if (index == 0) return command_result{error::database_empty_result};
|
||||
this->sendCommand(result);
|
||||
size_t index{0};
|
||||
ts::command_builder notify{this->notify_response_command("notifychannelgroupclientlist"), 64, result.size()};
|
||||
for(const auto& entry : result) {
|
||||
auto bulk = notify.bulk(index++);
|
||||
bulk.put_unchecked("cgid", std::get<0>(entry));
|
||||
bulk.put_unchecked("cid", std::get<1>(entry));
|
||||
bulk.put_unchecked("cldbid", std::get<2>(entry));
|
||||
}
|
||||
this->sendCommand(notify);
|
||||
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
@@ -509,9 +594,15 @@ command_result ConnectedClient::handleCommandChannelGroupPermList(Command &cmd)
|
||||
CMD_CHK_AND_INC_FLOOD_POINTS(5);
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_channelgroup_permission_list, 1);
|
||||
|
||||
auto channelGroup = (this->server ? this->server->group_manager() : serverInstance->group_manager().get())->findGroup(cmd["cgid"].as<GroupId>());
|
||||
if (!channelGroup || channelGroup->target() != GROUPTARGET_CHANNEL) return command_result{error::parameter_invalid, "invalid channel group id"};
|
||||
if (!this->notifyGroupPermList(channelGroup, cmd.hasParm("permsid"))) return command_result{error::database_empty_result};
|
||||
auto group_manager = this->server ? this->server->group_manager() : serverInstance->group_manager();
|
||||
auto channelGroup = group_manager->channel_groups()->find_group(groups::GroupCalculateMode::GLOBAL, cmd["cgid"].as<GroupId>());
|
||||
if (!channelGroup) {
|
||||
return command_result{error::group_invalid_id};
|
||||
}
|
||||
|
||||
if (!this->notifyGroupPermList(channelGroup, cmd.hasParm("permsid"))) {
|
||||
return command_result{error::database_empty_result};
|
||||
}
|
||||
|
||||
if (this->getType() == ClientType::CLIENT_TEAMSPEAK && this->command_times.last_notify + this->command_times.notify_timeout < system_clock::now()) {
|
||||
this->sendTSPermEditorWarning();
|
||||
@@ -523,9 +614,11 @@ command_result ConnectedClient::handleCommandChannelGroupPermList(Command &cmd)
|
||||
command_result ConnectedClient::handleCommandChannelGroupAddPerm(Command &cmd) {
|
||||
CMD_CHK_AND_INC_FLOOD_POINTS(5);
|
||||
|
||||
auto group_manager = this->server ? this->server->group_manager() : serverInstance->group_manager().get();
|
||||
auto channelGroup = group_manager->findGroup(cmd["cgid"].as<GroupId>());
|
||||
if (!channelGroup || channelGroup->target() != GROUPTARGET_CHANNEL) return command_result{error::parameter_invalid, "invalid channel group id"};
|
||||
auto group_manager = this->server ? this->server->group_manager() : serverInstance->group_manager();
|
||||
auto channelGroup = group_manager->channel_groups()->find_group(groups::GroupCalculateMode::GLOBAL, cmd["cgid"].as<GroupId>());
|
||||
if (!channelGroup) {
|
||||
return command_result{error::group_invalid_id};
|
||||
}
|
||||
ACTION_REQUIRES_GROUP_PERMISSION(channelGroup, permission::i_channel_group_needed_modify_power, permission::i_channel_group_modify_power, true);
|
||||
|
||||
ts::command::bulk_parser::PermissionBulksParser<true> pparser{cmd};
|
||||
@@ -542,20 +635,14 @@ command_result ConnectedClient::handleCommandChannelGroupAddPerm(Command &cmd) {
|
||||
log::PermissionTarget::CHANNEL_GROUP,
|
||||
permission::v2::PermissionUpdateType::set_value,
|
||||
0, "",
|
||||
channelGroup->groupId(), channelGroup->name());
|
||||
channelGroup->group_id(), channelGroup->display_name());
|
||||
|
||||
updateList |= ppermission.is_group_property();
|
||||
}
|
||||
|
||||
if (updateList) {
|
||||
channelGroup->apply_properties_from_permissions();
|
||||
}
|
||||
|
||||
if (this->server) {
|
||||
if (updateList) {
|
||||
this->server->forEachClient([](shared_ptr<ConnectedClient> cl) {
|
||||
cl->notifyChannelGroupList();
|
||||
});
|
||||
this->server->enqueue_notify_channel_group_list();
|
||||
}
|
||||
|
||||
this->server->forEachClient([channelGroup](shared_ptr<ConnectedClient> cl) {
|
||||
@@ -575,9 +662,12 @@ command_result ConnectedClient::handleCommandChannelGroupAddPerm(Command &cmd) {
|
||||
|
||||
command_result ConnectedClient::handleCommandChannelGroupDelPerm(Command &cmd) {
|
||||
CMD_CHK_AND_INC_FLOOD_POINTS(5);
|
||||
auto group_manager = this->server ? this->server->group_manager() : serverInstance->group_manager().get();
|
||||
auto channelGroup = group_manager->findGroup(cmd["cgid"].as<GroupId>());
|
||||
if (!channelGroup || channelGroup->target() != GROUPTARGET_CHANNEL) return command_result{error::parameter_invalid, "invalid channel group id"};
|
||||
|
||||
auto group_manager = this->server ? this->server->group_manager() : serverInstance->group_manager();
|
||||
auto channelGroup = group_manager->channel_groups()->find_group(groups::GroupCalculateMode::GLOBAL, cmd["cgid"].as<GroupId>());
|
||||
if (!channelGroup) {
|
||||
return command_result{error::group_invalid_id};
|
||||
}
|
||||
ACTION_REQUIRES_GROUP_PERMISSION(channelGroup, permission::i_channel_group_needed_modify_power, permission::i_channel_group_modify_power, true);
|
||||
|
||||
ts::command::bulk_parser::PermissionBulksParser<false> pparser{cmd};
|
||||
@@ -593,18 +683,13 @@ command_result ConnectedClient::handleCommandChannelGroupDelPerm(Command &cmd) {
|
||||
log::PermissionTarget::CHANNEL_GROUP,
|
||||
permission::v2::PermissionUpdateType::delete_value,
|
||||
0, "",
|
||||
channelGroup->groupId(), channelGroup->name());
|
||||
channelGroup->group_id(), channelGroup->display_name());
|
||||
updateList |= ppermission.is_group_property();
|
||||
}
|
||||
|
||||
if (updateList)
|
||||
channelGroup->apply_properties_from_permissions();
|
||||
|
||||
if (this->server) {
|
||||
if (updateList)
|
||||
this->server->forEachClient([](shared_ptr<ConnectedClient> cl) {
|
||||
cl->notifyChannelGroupList();
|
||||
});
|
||||
this->server->enqueue_notify_channel_group_list();
|
||||
this->server->forEachClient([channelGroup](shared_ptr<ConnectedClient> cl) {
|
||||
unique_lock client_channel_lock(cl->channel_lock); /* while we're updating groups we dont want to change anything! */
|
||||
if (cl->channelGroupAssigned(channelGroup, cl->getChannel())) {
|
||||
@@ -632,7 +717,7 @@ command_result ConnectedClient::handleCommandChannelCreate(Command &cmd) {
|
||||
|
||||
#define test_permission(required, permission_type) \
|
||||
do { \
|
||||
if (!permission::v2::permission_granted(required, this->calculate_permission(permission_type, parent_channel_id, false))) \
|
||||
if (!permission::v2::permission_granted(required, this->calculate_permission(permission_type, parent_channel_id, false))) \
|
||||
return command_result{permission_type}; \
|
||||
} while (0)
|
||||
|
||||
@@ -842,22 +927,25 @@ command_result ConnectedClient::handleCommandChannelCreate(Command &cmd) {
|
||||
max_channels = this->calculate_permission(permission::i_client_max_permanent_channels, parent_channel_id, false);
|
||||
|
||||
if (max_channels.has_value) {
|
||||
if (!permission::v2::permission_granted(created_perm + 1, max_channels))
|
||||
if (!permission::v2::permission_granted(created_perm + 1, max_channels)) {
|
||||
return command_result{permission::i_client_max_permanent_channels};
|
||||
}
|
||||
}
|
||||
} else if (cmd[0]["channel_flag_semi_permanent"].as<bool>()) {
|
||||
max_channels = this->calculate_permission(permission::i_client_max_semi_channels, parent_channel_id, false);
|
||||
|
||||
if (max_channels.has_value) {
|
||||
if (!permission::v2::permission_granted(created_semi + 1, max_channels))
|
||||
if (!permission::v2::permission_granted(created_semi + 1, max_channels)) {
|
||||
return command_result{permission::i_client_max_semi_channels};
|
||||
}
|
||||
}
|
||||
} else {
|
||||
max_channels = this->calculate_permission(permission::i_client_max_temporary_channels, parent_channel_id, false);
|
||||
|
||||
if (max_channels.has_value) {
|
||||
if (!permission::v2::permission_granted(created_tmp + 1, max_channels))
|
||||
if (!permission::v2::permission_granted(created_tmp + 1, max_channels)) {
|
||||
return command_result{permission::i_client_max_temporary_channels};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -873,7 +961,9 @@ command_result ConnectedClient::handleCommandChannelCreate(Command &cmd) {
|
||||
channel_deep++;
|
||||
{
|
||||
const auto typed_parent = dynamic_pointer_cast<ServerChannel>(local_parent->entry);
|
||||
if (typed_parent->deleted) return command_result{error::channel_is_deleted, "One of the parents has been deleted"};
|
||||
if (typed_parent->deleted) {
|
||||
return command_result{error::channel_is_deleted, "One of the parents has been deleted"};
|
||||
}
|
||||
}
|
||||
local_parent = local_parent->parent.lock();
|
||||
}
|
||||
@@ -955,15 +1045,23 @@ command_result ConnectedClient::handleCommandChannelCreate(Command &cmd) {
|
||||
if (this->server) {
|
||||
const auto self_lock = this->ref();
|
||||
|
||||
GroupId adminGroup = this->server->properties()[property::VIRTUALSERVER_DEFAULT_CHANNEL_ADMIN_GROUP];
|
||||
auto channel_admin_group = this->server->group_manager()->findGroup(adminGroup);
|
||||
if (!channel_admin_group) {
|
||||
logError(this->getServerId(), "Missing server's default channel admin group! Using default channel group!");
|
||||
channel_admin_group = this->server->group_manager()->defaultGroup(GroupTarget::GROUPTARGET_CHANNEL);
|
||||
auto admin_group_id = this->server->properties()[property::VIRTUALSERVER_DEFAULT_CHANNEL_ADMIN_GROUP].as_or<GroupId>(0);
|
||||
auto admin_group = this->server->group_manager()->channel_groups()->find_group(groups::GroupCalculateMode::GLOBAL, admin_group_id);
|
||||
if(!admin_group) {
|
||||
logError(this->getServerId(), "Missing servers default channel admin group {}. Using the default channel gropup.", admin_group_id);
|
||||
admin_group = this->server->default_channel_group();
|
||||
}
|
||||
|
||||
/* FIXME: Log group assignment */
|
||||
this->server->group_manager()->setChannelGroup(this->getClientDatabaseId(), channel_admin_group, created_channel);
|
||||
/* admin_group might still be null since default_channel_group() could return nullptr */
|
||||
if(admin_group) {
|
||||
this->server->group_manager()->assignments().set_channel_group(this->getClientDatabaseId(), created_channel->channelId(), admin_group->group_id(), false);
|
||||
serverInstance->action_logger()->group_assignment_logger.log_group_assignment_remove(
|
||||
this->getServerId(), this->server->getServerRoot(),
|
||||
log::GroupTarget::CHANNEL,
|
||||
admin_group->group_id(), admin_group->display_name(),
|
||||
this->getClientDatabaseId(), this->getDisplayName()
|
||||
);
|
||||
}
|
||||
|
||||
if (created_channel->channelType() == ChannelType::temporary && (this->getType() == ClientType::CLIENT_TEAMSPEAK || this->getType() == ClientType::CLIENT_WEB || this->getType() == ClientType::CLIENT_TEASPEAK)) {
|
||||
channel_tree_read_lock.unlock();
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include "../../manager/ConversationManager.h"
|
||||
#include "../../manager/PermissionNameMapper.h"
|
||||
#include "../../manager/ActionLogger.h"
|
||||
#include "../../groups/GroupManager.h"
|
||||
#include "../../absl/btree/map.h"
|
||||
#include <experimental/filesystem>
|
||||
#include <cstdint>
|
||||
#include <StringVariable.h>
|
||||
@@ -443,28 +445,41 @@ command_result ConnectedClient::handleCommandSetClientChannelGroup(Command &cmd)
|
||||
CMD_RESET_IDLE;
|
||||
CMD_CHK_AND_INC_FLOOD_POINTS(25);
|
||||
|
||||
auto serverGroup = this->server->group_manager()->findGroup(cmd["cgid"].as<GroupId>());
|
||||
if (!serverGroup && cmd["cgid"].as<GroupId>() == 0)
|
||||
serverGroup = this->server->group_manager()->defaultGroup(GroupTarget::GROUPTARGET_CHANNEL);
|
||||
auto target_channel_group_id = cmd["cgid"].as<GroupId>();
|
||||
std::shared_ptr<groups::ChannelGroup> target_channel_group{}, default_channel_group{};
|
||||
|
||||
if (!serverGroup || serverGroup->target() != GROUPTARGET_CHANNEL)
|
||||
return command_result{error::group_invalid_id};
|
||||
default_channel_group = this->server->default_channel_group();
|
||||
if(target_channel_group_id == 0) {
|
||||
target_channel_group = default_channel_group;
|
||||
if(!target_channel_group) {
|
||||
return command_result{error::vs_critical};
|
||||
}
|
||||
} else {
|
||||
target_channel_group = this->server->group_manager()->channel_groups()->find_group(groups::GroupCalculateMode::GLOBAL, cmd["cgid"].as<GroupId>());
|
||||
if(!target_channel_group) {
|
||||
return command_result{error::group_invalid_id};
|
||||
}
|
||||
}
|
||||
|
||||
shared_lock server_channel_lock(this->server->channel_tree_lock); /* ensure we dont get moved or somebody could move us */
|
||||
shared_lock server_channel_lock{this->server->channel_tree_lock}; /* ensure we dont get moved or somebody could move us */
|
||||
auto channel_id = cmd["cid"].as<ChannelId>();
|
||||
auto channel = this->server->channelTree->findChannel(channel_id);
|
||||
if (!channel) return command_result{error::channel_invalid_id};
|
||||
if (!channel) {
|
||||
return command_result{error::channel_invalid_id};
|
||||
}
|
||||
|
||||
auto target_cldbid = cmd["cldbid"].as<ClientDbId>();
|
||||
{
|
||||
auto channel_group_member_add_power = this->calculate_permission(permission::i_channel_group_member_add_power, channel_id);
|
||||
if(!serverGroup->permission_granted(permission::i_channel_group_needed_member_add_power, channel_group_member_add_power, true)) {
|
||||
if(target_cldbid != this->getClientDatabaseId())
|
||||
if(!target_channel_group->permission_granted(permission::i_channel_group_needed_member_add_power, channel_group_member_add_power, true)) {
|
||||
if(target_cldbid != this->getClientDatabaseId()) {
|
||||
return command_result{permission::i_channel_group_member_add_power};
|
||||
}
|
||||
|
||||
auto channel_group_self_add_power = this->calculate_permission(permission::i_channel_group_self_add_power, channel_id);
|
||||
if(!serverGroup->permission_granted(permission::i_channel_group_needed_member_add_power, channel_group_self_add_power, true))
|
||||
if(!target_channel_group->permission_granted(permission::i_channel_group_needed_member_add_power, channel_group_self_add_power, true)) {
|
||||
return command_result{permission::i_channel_group_self_add_power};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -474,66 +489,68 @@ command_result ConnectedClient::handleCommandSetClientChannelGroup(Command &cmd)
|
||||
|
||||
|
||||
if(client_needed_permission_modify_power.has_value) {
|
||||
if(!permission::v2::permission_granted(client_needed_permission_modify_power, client_permission_modify_power))
|
||||
if(!permission::v2::permission_granted(client_needed_permission_modify_power, client_permission_modify_power)) {
|
||||
return command_result{permission::i_client_permission_modify_power};
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<GroupAssignment> old_group;
|
||||
{
|
||||
old_group = this->server->group_manager()->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(!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(!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->group_manager()->setChannelGroup(target_cldbid, serverGroup, channel);
|
||||
auto old_group_id = this->server->group_manager()->assignments().exact_channel_group_of_client(groups::GroupAssignmentCalculateMode::GLOBAL, target_cldbid, channel->channelId());
|
||||
std::shared_ptr<groups::ChannelGroup> old_group{};
|
||||
|
||||
if(old_group_id.has_value()) {
|
||||
old_group = this->server->group_manager()->channel_groups()->find_group(groups::GroupCalculateMode::GLOBAL, old_group_id->group_id);
|
||||
if(old_group) {
|
||||
auto channel_group_member_remove_power = this->calculate_permission(permission::i_channel_group_member_remove_power, channel_id);
|
||||
if(!old_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(!old_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->group_manager()->assignments().set_channel_group(target_cldbid, target_channel_group->group_id(), channel->channelId(), !target_channel_group->is_permanent());
|
||||
|
||||
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->group_manager()->update_server_group_property(targetClient, false, targetClient->getChannel()); /* needs a write lock */
|
||||
client_channel_lock_w.unlock();
|
||||
shared_lock client_channel_lock_r(targetClient->channel_lock);
|
||||
auto result = this->server->notifyClientPropertyUpdates(targetClient, updates);
|
||||
if (result) {
|
||||
targetClient->task_update_needed_permissions.enqueue();
|
||||
bool channel_group_changed, server_group_changed;
|
||||
targetClient->update_displayed_client_groups(server_group_changed, channel_group_changed);
|
||||
|
||||
if(targetClient->properties()[property::CLIENT_CHANNEL_GROUP_INHERITED_CHANNEL_ID] == channel->channelId()) { //Only if group assigned over the channel
|
||||
for (const auto &viewer : this->server->getClients()) {
|
||||
/* if in view will be tested within that method */
|
||||
shared_lock viewer_channel_lock(viewer->channel_lock, defer_lock);
|
||||
if(viewer != targetClient)
|
||||
viewer_channel_lock.lock();
|
||||
viewer->notifyClientChannelGroupChanged(this->ref(), targetClient, targetClient->getChannel(), channel, serverGroup, false);
|
||||
if(channel_group_changed) {
|
||||
targetClient->task_update_needed_permissions.enqueue();
|
||||
targetClient->task_update_displayed_groups.enqueue();
|
||||
|
||||
for (const auto &viewer : this->server->getClients()) {
|
||||
/* if in view will be tested within that method */
|
||||
std::shared_lock viewer_channel_lock{viewer->channel_lock, defer_lock};
|
||||
if(viewer != targetClient) {
|
||||
viewer_channel_lock.lock();
|
||||
}
|
||||
viewer->notifyClientChannelGroupChanged(this->ref(), targetClient, targetClient->getChannel(), channel, target_channel_group, false);
|
||||
}
|
||||
}
|
||||
|
||||
targetClient->task_update_channel_client_properties.enqueue();
|
||||
}
|
||||
|
||||
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(),
|
||||
old_group->group_id(), old_group->display_name(),
|
||||
target_cldbid, connected_client ? connected_client->getDisplayName() : ""
|
||||
);
|
||||
}
|
||||
if(serverGroup != this->server->group_manager()->defaultGroup(GroupTarget::GROUPTARGET_CHANNEL)) {
|
||||
|
||||
if(target_channel_group != default_channel_group) {
|
||||
serverInstance->action_logger()->group_assignment_logger.log_group_assignment_add(this->getServerId(),
|
||||
this->ref(), log::GroupTarget::CHANNEL,
|
||||
serverGroup->groupId(), serverGroup->name(),
|
||||
target_channel_group->group_id(), target_channel_group->display_name(),
|
||||
target_cldbid, connected_client ? connected_client->getDisplayName() : ""
|
||||
);
|
||||
}
|
||||
@@ -1241,8 +1258,8 @@ void check_token_action_permissions(const std::shared_ptr<ConnectedClient>& clie
|
||||
|
||||
switch(action.type) {
|
||||
case ActionType::AddServerGroup: {
|
||||
auto target_group = client->getServer()->group_manager()->findGroup(action.id1);
|
||||
if(!target_group || target_group->type() == GroupType::GROUP_TYPE_TEMPLATE || target_group->target() != GroupTarget::GROUPTARGET_SERVER) {
|
||||
auto target_group = client->getServer()->group_manager()->server_groups()->find_group(groups::GroupCalculateMode::GLOBAL, action.id1);
|
||||
if(!target_group || target_group->group_type() == groups::GroupType::GROUP_TYPE_TEMPLATE) {
|
||||
action.type = ActionType::ActionIgnore;
|
||||
result.set_result(index, ts::command_result{error::group_invalid_id});
|
||||
break;
|
||||
@@ -1258,8 +1275,8 @@ void check_token_action_permissions(const std::shared_ptr<ConnectedClient>& clie
|
||||
}
|
||||
|
||||
case ActionType::RemoveServerGroup: {
|
||||
auto target_group = client->getServer()->group_manager()->findGroup(action.id1);
|
||||
if(!target_group || target_group->type() == GroupType::GROUP_TYPE_TEMPLATE || target_group->target() != GroupTarget::GROUPTARGET_SERVER) {
|
||||
auto target_group = client->getServer()->group_manager()->channel_groups()->find_group(groups::GroupCalculateMode::GLOBAL, action.id1);
|
||||
if(!target_group || target_group->group_type() == groups::GroupType::GROUP_TYPE_TEMPLATE) {
|
||||
action.type = ActionType::ActionIgnore;
|
||||
result.set_result(index, ts::command_result{error::group_invalid_id});
|
||||
break;
|
||||
@@ -1275,8 +1292,8 @@ void check_token_action_permissions(const std::shared_ptr<ConnectedClient>& clie
|
||||
}
|
||||
|
||||
case ActionType::SetChannelGroup: {
|
||||
auto target_group = client->getServer()->group_manager()->findGroup(action.id1);
|
||||
if(!target_group || target_group->type() == GroupType::GROUP_TYPE_TEMPLATE || target_group->target() != GroupTarget::GROUPTARGET_CHANNEL) {
|
||||
auto target_group = client->getServer()->group_manager()->server_groups()->find_group(groups::GroupCalculateMode::GLOBAL, action.id1);
|
||||
if(!target_group || target_group->group_type() == groups::GroupType::GROUP_TYPE_TEMPLATE) {
|
||||
action.type = ActionType::ActionIgnore;
|
||||
result.set_result(index, ts::command_result{error::group_invalid_id});
|
||||
break;
|
||||
@@ -2029,8 +2046,10 @@ command_result ConnectedClient::handleCommandPermFind(Command &cmd) {
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
if(entries.empty())
|
||||
|
||||
if(entries.empty()) {
|
||||
return command_result{error::database_empty_result};
|
||||
}
|
||||
|
||||
struct CommandPerm {
|
||||
permission::PermissionType p;
|
||||
@@ -2044,7 +2063,16 @@ command_result ConnectedClient::handleCommandPermFind(Command &cmd) {
|
||||
perms.resize(entries.size());
|
||||
|
||||
size_t index{0};
|
||||
auto all_groups = this->server->group_manager()->availableGroups(true);
|
||||
|
||||
/* 1 := Server | 2 := Channel */
|
||||
btree::map<GroupId, int> group_types{};
|
||||
for(const auto& s_group : this->server->group_manager()->server_groups()->available_groups(groups::GroupCalculateMode::GLOBAL)) {
|
||||
group_types[s_group->group_id()] = 1;
|
||||
}
|
||||
for(const auto& c_group : this->server->group_manager()->channel_groups()->available_groups(groups::GroupCalculateMode::GLOBAL)) {
|
||||
group_types[c_group->group_id()] = 2;
|
||||
}
|
||||
|
||||
for(const auto& entry : entries) {
|
||||
auto& perm = perms[index++];
|
||||
|
||||
@@ -2090,19 +2118,24 @@ command_result ConnectedClient::handleCommandPermFind(Command &cmd) {
|
||||
perm.id2 = 0;
|
||||
perm.t = 2; /* channel permission */
|
||||
} else if(entry->type == permission::SQL_PERM_GROUP) {
|
||||
auto group = std::find_if(all_groups.begin(), all_groups.end(), [&](const auto& group) { return group->groupId() == entry->group_id; });
|
||||
if(group == all_groups.end()) {
|
||||
index--; /* unknown group */
|
||||
continue;
|
||||
}
|
||||
if((*group)->target() == GroupTarget::GROUPTARGET_CHANNEL) {
|
||||
perm.id1 = 0;
|
||||
perm.id2 = entry->group_id;
|
||||
perm.t = 3; /* channel group */
|
||||
} else {
|
||||
perm.id1 = entry->group_id;
|
||||
perm.id2 = 0;
|
||||
perm.t = 0; /* server group */
|
||||
auto group_type = group_types[entry->group_id];
|
||||
switch(group_type) {
|
||||
case 1:
|
||||
perm.id1 = entry->group_id;
|
||||
perm.id2 = 0;
|
||||
perm.t = 0; /* server group */
|
||||
break;
|
||||
|
||||
case 2:
|
||||
perm.id1 = 0;
|
||||
perm.id2 = entry->group_id;
|
||||
perm.t = 3; /* channel group */
|
||||
break;
|
||||
|
||||
case 0:
|
||||
default:
|
||||
/* unknown group */
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -2128,21 +2161,6 @@ command_result ConnectedClient::handleCommandPermFind(Command &cmd) {
|
||||
return &a > &b;
|
||||
});
|
||||
|
||||
#if 0
|
||||
Command result(this->notify_response_command("notifypermfind"));
|
||||
index = 0;
|
||||
|
||||
// http://yat.qa/ressourcen/server-query-kommentare/#permfind
|
||||
for(const auto& e : perms) {
|
||||
result[index]["p"] = e.p;
|
||||
result[index]["v"] = e.v;
|
||||
result[index]["id1"] = e.id1;
|
||||
result[index]["id2"] = e.id2;
|
||||
result[index]["t"] = e.t;
|
||||
index++;
|
||||
}
|
||||
this->sendCommand(result);
|
||||
#else
|
||||
command_builder result{this->notify_response_command("notifypermfind"), 64, perms.size()};
|
||||
index = 0;
|
||||
|
||||
@@ -2155,7 +2173,6 @@ command_result ConnectedClient::handleCommandPermFind(Command &cmd) {
|
||||
bulk.put("id2", e.id2);
|
||||
}
|
||||
this->sendCommand(result);
|
||||
#endif
|
||||
|
||||
return command_result{error::ok};
|
||||
}
|
||||
@@ -2171,7 +2188,9 @@ command_result ConnectedClient::handleCommandPermOverview(Command &cmd) {
|
||||
CMD_CHK_AND_INC_FLOOD_POINTS(5);
|
||||
|
||||
auto client_dbid = cmd["cldbid"].as<ClientDbId>();
|
||||
if(!serverInstance->databaseHelper()->validClientDatabaseId(this->getServer(), client_dbid)) return command_result{error::client_invalid_id};
|
||||
if(!serverInstance->databaseHelper()->validClientDatabaseId(this->getServer(), client_dbid)) {
|
||||
return command_result{error::client_invalid_id};
|
||||
}
|
||||
|
||||
if(client_dbid == this->getClientDatabaseId()) {
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_client_permissionoverview_own, 1);
|
||||
@@ -2182,26 +2201,28 @@ command_result ConnectedClient::handleCommandPermOverview(Command &cmd) {
|
||||
string channel_query, perm_query;
|
||||
|
||||
auto channel = this->server ? this->server->channelTree->findChannel(cmd["cid"]) : serverInstance->getChannelTree()->findChannel(cmd["cid"]);
|
||||
if(!channel) return command_result{error::channel_invalid_id};
|
||||
if(!channel) {
|
||||
return command_result{error::channel_invalid_id};
|
||||
}
|
||||
|
||||
auto server_groups = this->server->group_manager()->getServerGroups(client_dbid, ClientType::CLIENT_TEAMSPEAK);
|
||||
auto channel_group = this->server->group_manager()->getChannelGroup(client_dbid, channel, true);
|
||||
auto channel_group = this->assignedChannelGroup(channel);
|
||||
auto permission_manager = serverInstance->databaseHelper()->loadClientPermissionManager(this->getServerId(), client_dbid);
|
||||
|
||||
Command result(this->getExternalType() == ClientType::CLIENT_TEAMSPEAK ? "notifypermoverview" : "");
|
||||
size_t index = 0;
|
||||
result["cldbid"] = client_dbid;
|
||||
result["cid"] = channel->channelId();
|
||||
if(cmd["return_code"].size() > 0)
|
||||
if(cmd["return_code"].size() > 0) {
|
||||
result["return_code"] = cmd["return_code"].string();
|
||||
}
|
||||
|
||||
for(const auto& server_group : server_groups) {
|
||||
auto permission_manager = server_group->group->permissions();
|
||||
for(const auto& server_group : this->assignedServerGroups()) {
|
||||
auto permission_manager = server_group->permissions();
|
||||
for(const auto& permission_data : permission_manager->permissions()) {
|
||||
auto& permission = std::get<1>(permission_data);
|
||||
if(permission.flags.value_set) {
|
||||
result[index]["t"] = 0; /* server group */
|
||||
result[index]["id1"] = server_group->group->groupId();
|
||||
result[index]["id1"] = server_group->group_id();
|
||||
result[index]["id2"] = 0;
|
||||
|
||||
result[index]["p"] = std::get<0>(permission_data);
|
||||
@@ -2212,7 +2233,7 @@ command_result ConnectedClient::handleCommandPermOverview(Command &cmd) {
|
||||
}
|
||||
if(permission.flags.grant_set) {
|
||||
result[index]["t"] = 0; /* server group */
|
||||
result[index]["id1"] = server_group->group->groupId();
|
||||
result[index]["id1"] = server_group->group_id();
|
||||
result[index]["id2"] = 0;
|
||||
|
||||
result[index]["p"] = (std::get<0>(permission_data) | PERM_ID_GRANT);
|
||||
|
||||
Reference in New Issue
Block a user