1.4.14 ;)
This commit is contained in:
parent
3f98bcf9cf
commit
f6932f0512
@ -243,7 +243,7 @@ target_link_libraries(PermMapHelper
|
|||||||
|
|
||||||
SET(CPACK_PACKAGE_VERSION_MAJOR "1")
|
SET(CPACK_PACKAGE_VERSION_MAJOR "1")
|
||||||
SET(CPACK_PACKAGE_VERSION_MINOR "4")
|
SET(CPACK_PACKAGE_VERSION_MINOR "4")
|
||||||
SET(CPACK_PACKAGE_VERSION_PATCH "13")
|
SET(CPACK_PACKAGE_VERSION_PATCH "14")
|
||||||
if (BUILD_TYPE_NAME EQUAL OFF)
|
if (BUILD_TYPE_NAME EQUAL OFF)
|
||||||
SET(CPACK_PACKAGE_VERSION_DATA "beta")
|
SET(CPACK_PACKAGE_VERSION_DATA "beta")
|
||||||
elseif (BUILD_TYPE_NAME STREQUAL "")
|
elseif (BUILD_TYPE_NAME STREQUAL "")
|
||||||
|
@ -63,6 +63,8 @@ bool config::server::clients::teaspeak;
|
|||||||
std::string config::server::clients::extra_welcome_message_teaspeak;
|
std::string config::server::clients::extra_welcome_message_teaspeak;
|
||||||
config::server::clients::WelcomeMessageType config::server::clients::extra_welcome_message_type_teaspeak;
|
config::server::clients::WelcomeMessageType config::server::clients::extra_welcome_message_type_teaspeak;
|
||||||
|
|
||||||
|
bool config::server::clients::ignore_max_clone_permissions;
|
||||||
|
|
||||||
uint16_t config::voice::default_voice_port;
|
uint16_t config::voice::default_voice_port;
|
||||||
size_t config::voice::DefaultPuzzlePrecomputeSize;
|
size_t config::voice::DefaultPuzzlePrecomputeSize;
|
||||||
bool config::server::delete_missing_icon_permissions;
|
bool config::server::delete_missing_icon_permissions;
|
||||||
@ -1384,6 +1386,14 @@ std::deque<std::shared_ptr<EntryBinding>> config::create_bindings() {
|
|||||||
ADD_DESCRIPTION(std::to_string(WelcomeMessageType::WELCOME_MESSAGE_TYPE_POKE) + " - Message, pokes the client with the message when he enters the server");
|
ADD_DESCRIPTION(std::to_string(WelcomeMessageType::WELCOME_MESSAGE_TYPE_POKE) + " - Message, pokes the client with the message when he enters the server");
|
||||||
ADD_NOTE_RELOADABLE();
|
ADD_NOTE_RELOADABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
CREATE_BINDING("ignore_max_clone_permissions", FLAG_RELOADABLE);
|
||||||
|
BIND_BOOL(config::server::clients::ignore_max_clone_permissions, false);
|
||||||
|
ADD_DESCRIPTION("Allows you to disable the permission checks for i_client_max_clones_uid, i_client_max_clones_ip and i_client_max_clones_hwid");
|
||||||
|
ADD_SENSITIVE();
|
||||||
|
ADD_NOTE_RELOADABLE();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
@ -107,6 +107,8 @@ namespace ts::config {
|
|||||||
extern bool teaweb;
|
extern bool teaweb;
|
||||||
extern std::string extra_welcome_message_teaweb;
|
extern std::string extra_welcome_message_teaweb;
|
||||||
extern WelcomeMessageType extra_welcome_message_type_teaweb;
|
extern WelcomeMessageType extra_welcome_message_type_teaweb;
|
||||||
|
|
||||||
|
extern bool ignore_max_clone_permissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern ssize_t max_virtual_server;
|
extern ssize_t max_virtual_server;
|
||||||
|
@ -633,18 +633,20 @@ namespace ts {
|
|||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct ConnectedLockedClient {
|
struct ConnectedLockedClient {
|
||||||
|
ConnectedLockedClient() {}
|
||||||
explicit ConnectedLockedClient(std::shared_ptr<T> client) : client{std::move(client)} {
|
explicit ConnectedLockedClient(std::shared_ptr<T> client) : client{std::move(client)} {
|
||||||
if(this->client)
|
if(this->client)
|
||||||
this->connection_lock = this->client->require_connected_state();
|
this->connection_lock = this->client->require_connected_state();
|
||||||
}
|
}
|
||||||
|
explicit ConnectedLockedClient(ConnectedLockedClient&& client) : client{std::move(client.client)}, connection_lock{std::move(client.connection_lock)} { }
|
||||||
|
|
||||||
inline ConnectedLockedClient<T> &operator=(const ConnectedLockedClient& other) {
|
inline ConnectedLockedClient &operator=(const ConnectedLockedClient& other) {
|
||||||
this->client = other.client;
|
this->client = other.client;
|
||||||
if(other)
|
if(other)
|
||||||
this->connection_lock = std::shared_lock{*other.connection_lock.mutex()}; /* if the other is true (state locked & client) than we could easily acquire a shared lock */
|
this->connection_lock = std::shared_lock{*other.connection_lock.mutex()}; /* if the other is true (state locked & client) than we could easily acquire a shared lock */
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ConnectedLockedClient<T> &operator=(ConnectedLockedClient&& other) {
|
inline ConnectedLockedClient &operator=(ConnectedLockedClient&& other) {
|
||||||
this->client = std::move(other.client);
|
this->client = std::move(other.client);
|
||||||
this->connection_lock = std::move(other.connection_lock);
|
this->connection_lock = std::move(other.connection_lock);
|
||||||
}
|
}
|
||||||
|
@ -532,6 +532,7 @@ command_result SpeakingClient::handleCommandClientInit(Command& cmd) {
|
|||||||
if(!this->server->verifyServerPassword(cmd["client_server_password"].string(), true))
|
if(!this->server->verifyServerPassword(cmd["client_server_password"].string(), true))
|
||||||
return command_result{error::server_invalid_password};
|
return command_result{error::server_invalid_password};
|
||||||
|
|
||||||
|
if(!config::server::clients::ignore_max_clone_permissions) {
|
||||||
size_t clones_uid = 0;
|
size_t clones_uid = 0;
|
||||||
size_t clones_ip = 0;
|
size_t clones_ip = 0;
|
||||||
size_t clones_hwid = 0;
|
size_t clones_hwid = 0;
|
||||||
@ -562,6 +563,7 @@ command_result SpeakingClient::handleCommandClientInit(Command& cmd) {
|
|||||||
return command_result{error:: client_too_many_clones_connected, "too many clones connected (hwid)"};
|
return command_result{error:: client_too_many_clones_connected, "too many clones connected (hwid)"};
|
||||||
}
|
}
|
||||||
TIMING_STEP(timings, "max clones ");
|
TIMING_STEP(timings, "max clones ");
|
||||||
|
}
|
||||||
|
|
||||||
auto banEntry = this->resolveActiveBan(this->getPeerIp());
|
auto banEntry = this->resolveActiveBan(this->getPeerIp());
|
||||||
if(banEntry) {
|
if(banEntry) {
|
||||||
|
@ -420,12 +420,12 @@ command_result ConnectedClient::handleCommandChannelGroupAddPerm(Command &cmd) {
|
|||||||
PARSE_PERMISSION(cmd);
|
PARSE_PERMISSION(cmd);
|
||||||
|
|
||||||
auto val = cmd[index]["permvalue"].as<permission::PermissionValue>();
|
auto val = cmd[index]["permvalue"].as<permission::PermissionValue>();
|
||||||
if(permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) {
|
if(!ignore_granted_values && permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) {
|
||||||
if(conOnError) continue;
|
if(conOnError) continue;
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ignore_granted_values && !permission::v2::permission_granted(1, this->calculate_permission(permType, 0, true))) {
|
if(!permission::v2::permission_granted(1, this->calculate_permission(permType, 0, true))) {
|
||||||
if(conOnError) continue;
|
if(conOnError) continue;
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
}
|
}
|
||||||
@ -475,8 +475,6 @@ command_result ConnectedClient::handleCommandChannelGroupDelPerm(Command &cmd) {
|
|||||||
if (!channelGroup || channelGroup->target() != GROUPTARGET_CHANNEL) return command_result{error::parameter_invalid, "invalid channel group id"};
|
if (!channelGroup || channelGroup->target() != GROUPTARGET_CHANNEL) return command_result{error::parameter_invalid, "invalid channel group id"};
|
||||||
ACTION_REQUIRES_GROUP_PERMISSION(channelGroup, permission::i_channel_group_needed_modify_power, permission::i_channel_group_modify_power, true);
|
ACTION_REQUIRES_GROUP_PERMISSION(channelGroup, permission::i_channel_group_needed_modify_power, permission::i_channel_group_modify_power, true);
|
||||||
|
|
||||||
auto ignore_granted_values = permission::v2::permission_granted(1, this->calculate_permission(permission::b_permission_modify_power_ignore, 0));
|
|
||||||
|
|
||||||
bool updateList = false;
|
bool updateList = false;
|
||||||
bool conOnError = cmd[0].has("continueonerror");
|
bool conOnError = cmd[0].has("continueonerror");
|
||||||
|
|
||||||
@ -484,7 +482,7 @@ command_result ConnectedClient::handleCommandChannelGroupDelPerm(Command &cmd) {
|
|||||||
for (int index = 0; index < cmd.bulkCount(); index++) {
|
for (int index = 0; index < cmd.bulkCount(); index++) {
|
||||||
PARSE_PERMISSION(cmd)
|
PARSE_PERMISSION(cmd)
|
||||||
|
|
||||||
if(!ignore_granted_values && !permission::v2::permission_granted(0, this->calculate_permission(permType, 0, true))) {
|
if(!permission::v2::permission_granted(0, this->calculate_permission(permType, 0, true))) {
|
||||||
if(conOnError) continue;
|
if(conOnError) continue;
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
}
|
}
|
||||||
@ -1494,12 +1492,12 @@ command_result ConnectedClient::handleCommandChannelAddPerm(Command &cmd) {
|
|||||||
PARSE_PERMISSION(cmd);
|
PARSE_PERMISSION(cmd);
|
||||||
|
|
||||||
auto val = cmd[index]["permvalue"].as<permission::PermissionValue>();
|
auto val = cmd[index]["permvalue"].as<permission::PermissionValue>();
|
||||||
if(permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) {
|
if(!ignore_granted_values && permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) {
|
||||||
if(conOnError) continue;
|
if(conOnError) continue;
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ignore_granted_values && !permission::v2::permission_granted(1, this->calculate_permission(permType, channel_id, true))) {
|
if(!permission::v2::permission_granted(1, this->calculate_permission(permType, channel_id, true))) {
|
||||||
if(conOnError) continue;
|
if(conOnError) continue;
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
}
|
}
|
||||||
@ -1595,7 +1593,7 @@ command_result ConnectedClient::handleCommandChannelDelPerm(Command &cmd) {
|
|||||||
for (int index = 0; index < cmd.bulkCount(); index++) {
|
for (int index = 0; index < cmd.bulkCount(); index++) {
|
||||||
PARSE_PERMISSION(cmd);
|
PARSE_PERMISSION(cmd);
|
||||||
|
|
||||||
if(!ignore_granted_values && !permission::v2::permission_granted(0, this->calculate_permission(permType, channel_id, true))) {
|
if(!permission::v2::permission_granted(0, this->calculate_permission(permType, channel_id, true))) {
|
||||||
if(conOnError) continue;
|
if(conOnError) continue;
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
}
|
}
|
||||||
@ -1730,14 +1728,12 @@ command_result ConnectedClient::handleCommandChannelClientDelPerm(Command &cmd)
|
|||||||
ACTION_REQUIRES_PERMISSION(permission::i_client_permission_modify_power, required_permissions, channel_id);
|
ACTION_REQUIRES_PERMISSION(permission::i_client_permission_modify_power, required_permissions, channel_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ignore_granted_values = permission::v2::permission_granted(1, this->calculate_permission(permission::b_permission_modify_power_ignore, channel_id));
|
|
||||||
|
|
||||||
bool conOnError = cmd[0].has("continueonerror"), update_view = false;
|
bool conOnError = cmd[0].has("continueonerror"), update_view = false;
|
||||||
auto cll = this->server->findClientsByCldbId(cldbid);
|
auto cll = this->server->findClientsByCldbId(cldbid);
|
||||||
for (int index = 0; index < cmd.bulkCount(); index++) {
|
for (int index = 0; index < cmd.bulkCount(); index++) {
|
||||||
PARSE_PERMISSION(cmd);
|
PARSE_PERMISSION(cmd);
|
||||||
|
|
||||||
if(!ignore_granted_values && !permission::v2::permission_granted(0, this->calculate_permission(permType, channel_id, true))) {
|
if(!permission::v2::permission_granted(0, this->calculate_permission(permType, channel_id, true))) {
|
||||||
if(conOnError) continue;
|
if(conOnError) continue;
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
}
|
}
|
||||||
@ -1813,12 +1809,12 @@ command_result ConnectedClient::handleCommandChannelClientAddPerm(Command &cmd)
|
|||||||
PARSE_PERMISSION(cmd);
|
PARSE_PERMISSION(cmd);
|
||||||
|
|
||||||
auto val = cmd[index]["permvalue"].as<permission::PermissionValue>();
|
auto val = cmd[index]["permvalue"].as<permission::PermissionValue>();
|
||||||
if(permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) {
|
if(!ignore_granted_values && permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) {
|
||||||
if(conOnError) continue;
|
if(conOnError) continue;
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ignore_granted_values && !permission::v2::permission_granted(1, this->calculate_permission(permType, channel_id, true))) {
|
if(!permission::v2::permission_granted(1, this->calculate_permission(permType, channel_id, true))) {
|
||||||
if(conOnError) continue;
|
if(conOnError) continue;
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "../../build.h"
|
#include "../../build.h"
|
||||||
@ -61,27 +62,57 @@ command_result ConnectedClient::handleCommandClientKick(Command &cmd) {
|
|||||||
CMD_REQ_SERVER;
|
CMD_REQ_SERVER;
|
||||||
CMD_CHK_AND_INC_FLOOD_POINTS(25);
|
CMD_CHK_AND_INC_FLOOD_POINTS(25);
|
||||||
|
|
||||||
ConnectedLockedClient client{this->server->find_client_by_id(cmd["clid"].as<ClientId>())};
|
std::vector<ConnectedLockedClient<ConnectedClient>> clients{};
|
||||||
if (!client) return command_result{error::client_invalid_id};
|
clients.reserve(cmd.bulkCount());
|
||||||
if (client->getType() == CLIENT_MUSIC) return command_result{error::client_invalid_type, "You cant kick a music bot!"};
|
|
||||||
std::shared_ptr<BasicChannel> targetChannel = nullptr;
|
|
||||||
auto type = cmd["reasonid"].as<ViewReasonId>();
|
|
||||||
if (type == ViewReasonId::VREASON_CHANNEL_KICK) {
|
|
||||||
auto channel = client->getChannel();
|
|
||||||
ACTION_REQUIRES_PERMISSION(permission::i_client_kick_from_channel_power, client->calculate_permission(permission::i_client_needed_kick_from_channel_power, client->getChannelId()), client->getChannelId());
|
|
||||||
targetChannel = this->server->channelTree->getDefaultChannel();
|
|
||||||
} else if (type == ViewReasonId::VREASON_SERVER_KICK) {
|
|
||||||
auto channel = client->getChannel();
|
|
||||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::i_client_kick_from_server_power, client->calculate_permission(permission::i_client_needed_kick_from_server_power, client->getChannelId()));
|
|
||||||
targetChannel = nullptr;
|
|
||||||
} else return command_result{error::not_implemented};
|
|
||||||
|
|
||||||
if (targetChannel) {
|
auto type = cmd["reasonid"].as<ViewReasonId>();
|
||||||
this->server->notify_client_kick(client.client, this->ref(), cmd["reasonmsg"].as<std::string>(), targetChannel);
|
auto single_client = cmd.bulkCount() == 1;
|
||||||
|
auto target_channel = type == ViewReasonId::VREASON_CHANNEL_KICK ? this->server->channelTree->getDefaultChannel() : nullptr;
|
||||||
|
auto kick_power = type == ViewReasonId::VREASON_CHANNEL_KICK ?
|
||||||
|
this->calculate_permission(permission::i_client_kick_from_channel_power, target_channel->channelId()) :
|
||||||
|
this->calculate_permission(permission::i_client_kick_from_server_power, 0);
|
||||||
|
|
||||||
|
for(size_t index = 0; index < cmd.bulkCount(); index++) {
|
||||||
|
ConnectedLockedClient<ConnectedClient> client{this->server->find_client_by_id(cmd[index]["clid"].as<ClientId>())};
|
||||||
|
|
||||||
|
if (!client) {
|
||||||
|
if(single_client)
|
||||||
|
return command_result{error::client_invalid_id};
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (client->getType() == CLIENT_MUSIC) {
|
||||||
|
if(single_client)
|
||||||
|
return command_result{error::client_invalid_type};
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(type == ViewReasonId::VREASON_CHANNEL_KICK) {
|
||||||
|
if(!permission::v2::permission_granted(client->calculate_permission(permission::i_client_needed_kick_from_channel_power, client->getChannelId()), kick_power)) {
|
||||||
|
if(single_client)
|
||||||
|
return command_result{permission::i_client_needed_kick_from_channel_power};
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(!permission::v2::permission_granted(client->calculate_permission(permission::i_client_needed_kick_from_server_power, client->getChannelId()), kick_power)) {
|
||||||
|
if(single_client)
|
||||||
|
return command_result{permission::i_client_needed_kick_from_server_power};
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clients.emplace_back(std::move(client));
|
||||||
|
}
|
||||||
|
if (clients.empty())
|
||||||
|
return command_result{error::database_empty_result};
|
||||||
|
|
||||||
|
for(auto& client : clients) {
|
||||||
|
if (target_channel) {
|
||||||
|
this->server->notify_client_kick(client.client, this->ref(), cmd["reasonmsg"].as<std::string>(), target_channel);
|
||||||
} else {
|
} else {
|
||||||
this->server->notify_client_kick(client.client, this->ref(), cmd["reasonmsg"].as<std::string>(), nullptr);
|
this->server->notify_client_kick(client.client, this->ref(), cmd["reasonmsg"].as<std::string>(), nullptr);
|
||||||
client->close_connection(system_clock::now() + seconds(1));
|
client->close_connection(system_clock::now() + seconds(1));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return command_result{error::ok};
|
return command_result{error::ok};
|
||||||
}
|
}
|
||||||
@ -130,16 +161,7 @@ command_result ConnectedClient::handleCommandClientMove(Command &cmd) {
|
|||||||
CMD_CHK_AND_INC_FLOOD_POINTS(10);
|
CMD_CHK_AND_INC_FLOOD_POINTS(10);
|
||||||
|
|
||||||
shared_lock server_channel_r_lock(this->server->channel_tree_lock);
|
shared_lock server_channel_r_lock(this->server->channel_tree_lock);
|
||||||
auto target_client_id = cmd["clid"].as<ClientId>();
|
|
||||||
ConnectedLockedClient target_client{target_client_id == 0 ? this->ref() : this->server->find_client_by_id(target_client_id)};
|
|
||||||
if(!target_client) {
|
|
||||||
return command_result{error::client_invalid_id, "Invalid target clid"};
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!target_client->getChannel()) {
|
|
||||||
if(target_client.client != this)
|
|
||||||
return command_result{error::client_invalid_id, "Invalid target clid"};
|
|
||||||
}
|
|
||||||
auto channel = this->server->channelTree->findChannel(cmd["cid"].as<ChannelId>());
|
auto channel = this->server->channelTree->findChannel(cmd["cid"].as<ChannelId>());
|
||||||
if (!channel) {
|
if (!channel) {
|
||||||
return command_result{error::channel_invalid_id};
|
return command_result{error::channel_invalid_id};
|
||||||
@ -155,11 +177,43 @@ command_result ConnectedClient::handleCommandClientMove(Command &cmd) {
|
|||||||
auto permission_error = this->calculate_and_get_join_state(channel);
|
auto permission_error = this->calculate_and_get_join_state(channel);
|
||||||
if(permission_error != permission::unknown) return command_result{permission_error};
|
if(permission_error != permission::unknown) return command_result{permission_error};
|
||||||
|
|
||||||
|
std::vector<ConnectedLockedClient<ConnectedClient>> clients{};
|
||||||
|
auto is_single_client = cmd.bulkCount() == 1;
|
||||||
|
|
||||||
|
for(size_t index{0}; index < cmd.bulkCount(); index++) {
|
||||||
|
auto target_client_id = cmd[index]["clid"].as<ClientId>();
|
||||||
|
ConnectedLockedClient target_client{target_client_id == 0 ? this->ref() : this->server->find_client_by_id(target_client_id)};
|
||||||
|
if(!target_client) {
|
||||||
|
if(is_single_client)
|
||||||
|
return command_result{error::client_invalid_id};
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!target_client->getChannel()) {
|
||||||
|
if(target_client.client != this) {
|
||||||
|
if(is_single_client)
|
||||||
|
return command_result{error::client_invalid_id};
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(target_client.client != this) {
|
||||||
|
if(!permission::v2::permission_granted(target_client->calculate_permission(permission::i_client_needed_move_power, 0), this->calculate_permission(permission::i_client_move_power, 0))) {
|
||||||
|
if(is_single_client)
|
||||||
|
return command_result{permission::i_client_move_power};
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clients.emplace_back(std::move(target_client));
|
||||||
|
}
|
||||||
|
if(clients.empty())
|
||||||
|
return command_result{error::database_empty_result};
|
||||||
|
|
||||||
if (!channel->properties()[property::CHANNEL_FLAG_MAXCLIENTS_UNLIMITED].as<bool>() || !channel->properties()[property::CHANNEL_FLAG_MAXFAMILYCLIENTS_UNLIMITED].as<bool>()) {
|
if (!channel->properties()[property::CHANNEL_FLAG_MAXCLIENTS_UNLIMITED].as<bool>() || !channel->properties()[property::CHANNEL_FLAG_MAXFAMILYCLIENTS_UNLIMITED].as<bool>()) {
|
||||||
if(!permission::v2::permission_granted(1, this->calculate_permission(permission::b_channel_join_ignore_maxclients, channel->channelId()))) {
|
if(!permission::v2::permission_granted(1, this->calculate_permission(permission::b_channel_join_ignore_maxclients, channel->channelId()))) {
|
||||||
if(!channel->properties()[property::CHANNEL_FLAG_MAXCLIENTS_UNLIMITED].as<bool>()) {
|
if(!channel->properties()[property::CHANNEL_FLAG_MAXCLIENTS_UNLIMITED].as<bool>()) {
|
||||||
auto maxClients = channel->properties()[property::CHANNEL_MAXCLIENTS].as<int32_t>();
|
auto maxClients = channel->properties()[property::CHANNEL_MAXCLIENTS].as<int32_t>();
|
||||||
if (maxClients >= 0 && maxClients <= this->server->getClientsByChannel(channel).size())
|
if (maxClients >= 0 && maxClients <= this->server->getClientsByChannel(channel).size() + clients.size())
|
||||||
return command_result{error::channel_maxclients_reached};
|
return command_result{error::channel_maxclients_reached};
|
||||||
}
|
}
|
||||||
if(!channel->properties()[property::CHANNEL_FLAG_MAXFAMILYCLIENTS_UNLIMITED].as<bool>()) {
|
if(!channel->properties()[property::CHANNEL_FLAG_MAXFAMILYCLIENTS_UNLIMITED].as<bool>()) {
|
||||||
@ -167,36 +221,43 @@ command_result ConnectedClient::handleCommandClientMove(Command &cmd) {
|
|||||||
|
|
||||||
if(channel->properties()[property::CHANNEL_FLAG_MAXFAMILYCLIENTS_INHERITED].as<bool>()) {
|
if(channel->properties()[property::CHANNEL_FLAG_MAXFAMILYCLIENTS_INHERITED].as<bool>()) {
|
||||||
family_root = channel;
|
family_root = channel;
|
||||||
while(family_root && family_root->properties()[property::CHANNEL_FLAG_MAXFAMILYCLIENTS_INHERITED].as<bool>()) family_root = family_root->parent();
|
while(family_root && family_root->properties()[property::CHANNEL_FLAG_MAXFAMILYCLIENTS_INHERITED].as<bool>())
|
||||||
|
family_root = family_root->parent();
|
||||||
}
|
}
|
||||||
if(family_root && !family_root->properties()[property::CHANNEL_FLAG_MAXFAMILYCLIENTS_UNLIMITED]) { //Could not be CHANNEL_FLAG_MAXFAMILYCLIENTS_INHERITED
|
if(family_root && !family_root->properties()[property::CHANNEL_FLAG_MAXFAMILYCLIENTS_UNLIMITED]) { //Could not be CHANNEL_FLAG_MAXFAMILYCLIENTS_INHERITED
|
||||||
auto maxClients = family_root->properties()[property::CHANNEL_MAXFAMILYCLIENTS].as<int32_t>();
|
auto maxClients = family_root->properties()[property::CHANNEL_MAXFAMILYCLIENTS].as<int32_t>();
|
||||||
auto clients = 0;
|
auto client_count = 0;
|
||||||
for(const auto& entry : this->server->getClientsByChannelRoot(channel, false)) if(entry.get() != this) clients++; //Dont count the client itself
|
for(const auto& entry : this->server->getClientsByChannelRoot(channel, false))
|
||||||
if (maxClients >= 0 && maxClients <= clients)
|
if(entry.get() != this) client_count++; //Dont count the client itself
|
||||||
|
|
||||||
|
if (maxClients >= 0 && maxClients <= client_count + clients.size())
|
||||||
return command_result{error::channel_maxfamily_reached};
|
return command_result{error::channel_maxfamily_reached};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target_client.client != this)
|
|
||||||
ACTION_REQUIRES_PERMISSION(permission::i_client_move_power, target_client->calculate_permission(permission::i_client_needed_move_power, target_client->getChannelId()), target_client->getChannelId());
|
|
||||||
|
|
||||||
server_channel_r_lock.unlock();
|
server_channel_r_lock.unlock();
|
||||||
unique_lock server_channel_w_lock(this->server->channel_tree_lock);
|
unique_lock server_channel_w_lock(this->server->channel_tree_lock);
|
||||||
auto oldChannel = target_client->getChannel();
|
std::vector<std::shared_ptr<BasicChannel>> channels{};
|
||||||
|
channels.reserve(clients.size());
|
||||||
|
|
||||||
|
for(auto& client : clients) {
|
||||||
|
auto oldChannel = client->getChannel();
|
||||||
this->server->client_move(
|
this->server->client_move(
|
||||||
target_client.client,
|
client.client,
|
||||||
channel,
|
channel,
|
||||||
target_client.client == this ? nullptr : _this.lock(),
|
client.client == this ? nullptr : _this.lock(),
|
||||||
"",
|
"",
|
||||||
target_client.client == this ? ViewReasonId::VREASON_USER_ACTION : ViewReasonId::VREASON_MOVED,
|
client.client == this ? ViewReasonId::VREASON_USER_ACTION : ViewReasonId::VREASON_MOVED,
|
||||||
true,
|
true,
|
||||||
server_channel_w_lock
|
server_channel_w_lock
|
||||||
);
|
);
|
||||||
|
if(std::find_if(channels.begin(), channels.end(), [&](const std::shared_ptr<BasicChannel>& channel) { return &*channel == &*oldChannel; }) == channels.end())
|
||||||
|
channels.push_back(oldChannel);
|
||||||
|
}
|
||||||
|
|
||||||
if(oldChannel) {
|
for(auto oldChannel : channels) {
|
||||||
if(!server_channel_w_lock.owns_lock())
|
if(!server_channel_w_lock.owns_lock())
|
||||||
server_channel_w_lock.lock();
|
server_channel_w_lock.lock();
|
||||||
if(oldChannel->channelType() == ChannelType::temporary && oldChannel->properties()[property::CHANNEL_DELETE_DELAY].as<int64_t>() == 0)
|
if(oldChannel->channelType() == ChannelType::temporary && oldChannel->properties()[property::CHANNEL_DELETE_DELAY].as<int64_t>() == 0)
|
||||||
@ -213,11 +274,40 @@ command_result ConnectedClient::handleCommandClientPoke(Command &cmd) {
|
|||||||
CMD_RESET_IDLE;
|
CMD_RESET_IDLE;
|
||||||
CMD_CHK_AND_INC_FLOOD_POINTS(25);
|
CMD_CHK_AND_INC_FLOOD_POINTS(25);
|
||||||
|
|
||||||
ConnectedLockedClient client{ this->server->find_client_by_id(cmd["clid"].as<ClientId>())};
|
std::vector<ConnectedLockedClient<ConnectedClient>> clients{};
|
||||||
if (!client) return command_result{error::client_invalid_id};
|
clients.resize(cmd.bulkCount());
|
||||||
if (client->getType() == CLIENT_MUSIC) return command_result{error::client_invalid_type};
|
|
||||||
ACTION_REQUIRES_PERMISSION(permission::i_client_poke_power, client->calculate_permission(permission::i_client_needed_poke_power, client->getChannelId()), client->getChannelId());
|
|
||||||
|
|
||||||
|
bool is_single_poke = cmd.bulkCount() == 1;
|
||||||
|
for(size_t index{0}; index < cmd.bulkCount(); index++) {
|
||||||
|
ConnectedLockedClient client{ this->server->find_client_by_id(cmd["clid"].as<ClientId>())};
|
||||||
|
if (!client) {
|
||||||
|
if(is_single_poke)
|
||||||
|
return command_result{error::client_invalid_id};
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (client->getType() == CLIENT_MUSIC) {
|
||||||
|
if(is_single_poke)
|
||||||
|
return command_result{error::client_invalid_type};
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto own_permission = this->calculate_permission(permission::i_client_poke_power, client->getChannelId());
|
||||||
|
if(!permission::v2::permission_granted(client->calculate_permission(permission::i_client_needed_poke_power, client->getChannelId()), own_permission)) {
|
||||||
|
if(is_single_poke)
|
||||||
|
return command_result{permission::i_client_poke_power};
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
clients.push_back(std::move(client));
|
||||||
|
}
|
||||||
|
if(clients.empty())
|
||||||
|
return command_result{error::database_empty_result};
|
||||||
|
else if(clients.size() > 1) {
|
||||||
|
auto max_clients = this->calculate_permission(permission::i_client_poke_max_clients, 0);
|
||||||
|
if(!permission::v2::permission_granted(clients.size(), max_clients))
|
||||||
|
return command_result{permission::i_client_poke_max_clients};
|
||||||
|
}
|
||||||
|
for(auto& client : clients)
|
||||||
client->notifyClientPoke(_this.lock(), cmd["msg"]);
|
client->notifyClientPoke(_this.lock(), cmd["msg"]);
|
||||||
return command_result{error::ok};
|
return command_result{error::ok};
|
||||||
}
|
}
|
||||||
@ -884,12 +974,12 @@ command_result ConnectedClient::handleCommandClientAddPerm(Command &cmd) {
|
|||||||
PARSE_PERMISSION(cmd);
|
PARSE_PERMISSION(cmd);
|
||||||
|
|
||||||
auto val = cmd[index]["permvalue"].as<permission::PermissionValue>();
|
auto val = cmd[index]["permvalue"].as<permission::PermissionValue>();
|
||||||
if(permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) {
|
if(!ignore_granted_values && permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) {
|
||||||
if(conOnError) continue;
|
if(conOnError) continue;
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ignore_granted_values && !permission::v2::permission_granted(1, this->calculate_permission(permType, 0, true))) {
|
if(!permission::v2::permission_granted(1, this->calculate_permission(permType, 0, true))) {
|
||||||
if(conOnError) continue;
|
if(conOnError) continue;
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
}
|
}
|
||||||
@ -926,14 +1016,13 @@ command_result ConnectedClient::handleCommandClientDelPerm(Command &cmd) {
|
|||||||
auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cldbid);
|
auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cldbid);
|
||||||
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::i_client_permission_modify_power, this->server->calculate_permission(permission::i_client_needed_permission_modify_power, cldbid, ClientType::CLIENT_TEAMSPEAK, 0));
|
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::i_client_permission_modify_power, this->server->calculate_permission(permission::i_client_needed_permission_modify_power, cldbid, ClientType::CLIENT_TEAMSPEAK, 0));
|
||||||
|
|
||||||
auto ignore_granted_values = permission::v2::permission_granted(1, this->calculate_permission(permission::b_permission_modify_power_ignore, 0));
|
|
||||||
bool conOnError = cmd[0].has("continueonerror");
|
bool conOnError = cmd[0].has("continueonerror");
|
||||||
auto onlineClients = this->server->findClientsByCldbId(cmd["cldbid"]);
|
auto onlineClients = this->server->findClientsByCldbId(cmd["cldbid"]);
|
||||||
auto update_channel = false;
|
auto update_channel = false;
|
||||||
for (int index = 0; index < cmd.bulkCount(); index++) {
|
for (int index = 0; index < cmd.bulkCount(); index++) {
|
||||||
PARSE_PERMISSION(cmd)
|
PARSE_PERMISSION(cmd)
|
||||||
|
|
||||||
if(!ignore_granted_values && !permission::v2::permission_granted(0, this->calculate_permission(permType, 0, true))) {
|
if(!permission::v2::permission_granted(0, this->calculate_permission(permType, 0, true))) {
|
||||||
if(conOnError) continue;
|
if(conOnError) continue;
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
}
|
}
|
||||||
|
@ -819,12 +819,12 @@ command_result ConnectedClient::handleCommandServerGroupAddPerm(Command &cmd) {
|
|||||||
//permvalue='1' permnegated='0' permskip='0'
|
//permvalue='1' permnegated='0' permskip='0'
|
||||||
|
|
||||||
auto val = cmd[index]["permvalue"].as<permission::PermissionValue>();
|
auto val = cmd[index]["permvalue"].as<permission::PermissionValue>();
|
||||||
if(permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) {
|
if(!ignore_granted_values && permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) {
|
||||||
if(conOnError) continue;
|
if(conOnError) continue;
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ignore_granted_values && !permission::v2::permission_granted(1, this->calculate_permission(permType, 0, true))) {
|
if(!permission::v2::permission_granted(1, this->calculate_permission(permType, 0, true))) {
|
||||||
if(conOnError) continue;
|
if(conOnError) continue;
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
}
|
}
|
||||||
@ -895,7 +895,7 @@ command_result ConnectedClient::handleCommandServerGroupDelPerm(Command &cmd) {
|
|||||||
for (int index = 0; index < cmd.bulkCount(); index++) {
|
for (int index = 0; index < cmd.bulkCount(); index++) {
|
||||||
PARSE_PERMISSION(cmd);
|
PARSE_PERMISSION(cmd);
|
||||||
|
|
||||||
if(!ignore_granted_values && !permission::v2::permission_granted(0, this->calculate_permission(permType, 0, true))) {
|
if(!permission::v2::permission_granted(0, this->calculate_permission(permType, 0, true))) {
|
||||||
if(conOnError) continue;
|
if(conOnError) continue;
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,7 @@ namespace ts {
|
|||||||
CompressionHandler compress_handler;
|
CompressionHandler compress_handler;
|
||||||
AcknowledgeManager acknowledge_handler;
|
AcknowledgeManager acknowledge_handler;
|
||||||
|
|
||||||
std::atomic_bool should_reassembled_reschedule; /* this get checked as soon the command handle lock has been released so trylock will succeed */
|
std::atomic_bool should_reassembled_reschedule{}; /* this get checked as soon the command handle lock has been released so trylock will succeed */
|
||||||
|
|
||||||
//Handle stuff
|
//Handle stuff
|
||||||
void execute_handle_command_packets(const std::chrono::system_clock::time_point& /* scheduled */);
|
void execute_handle_command_packets(const std::chrono::system_clock::time_point& /* scheduled */);
|
||||||
@ -113,8 +113,8 @@ namespace ts {
|
|||||||
|
|
||||||
|
|
||||||
/* ---------- Write declarations ---------- */
|
/* ---------- Write declarations ---------- */
|
||||||
spin_lock write_queue_lock; /* queue access isn't for long in general */
|
spin_lock write_queue_lock{}; /* queue access isn't for long in general */
|
||||||
std::deque<pipes::buffer> write_queue;
|
std::deque<pipes::buffer> write_queue{};
|
||||||
|
|
||||||
struct WritePreprocessCategory {
|
struct WritePreprocessCategory {
|
||||||
enum value {
|
enum value {
|
||||||
|
2
shared
2
shared
@ -1 +1 @@
|
|||||||
Subproject commit 0b06a87fa4fb0d45221e073317afc0c503f4c14a
|
Subproject commit 2725c57f2e8c75a2bd8eae1ff477de3a33241cc9
|
Loading…
Reference in New Issue
Block a user