A lot of updates

This commit is contained in:
WolverinDEV
2020-05-07 21:28:15 +02:00
parent fd256411d1
commit 48326bd102
31 changed files with 3011 additions and 763 deletions
@@ -0,0 +1,5 @@
//
// Created by WolverinDEV on 07/05/2020.
//
#include "bulk_parsers.h"
@@ -0,0 +1,240 @@
#pragma once
#include <vector>
#include <query/Command.h>
#include <Error.h>
#include <PermissionManager.h>
#include <src/client/ConnectedClient.h>
#include "./helpers.h"
namespace ts::command::bulk_parser {
template <bool kParseValue>
class PermissionBulkParser {
public:
explicit PermissionBulkParser(ts::ParameterBulk& bulk) {
if(bulk.has("permid")) {
auto type = bulk["permid"].as<permission::PermissionType>();
if ((type & PERM_ID_GRANT) != 0) {
type &= ~PERM_ID_GRANT;
}
this->permission_ = permission::resolvePermissionData(type);
} else if(bulk.has("permsid")) {
auto permission_name = bulk["permsid"].string();
this->permission_ = permission::resolvePermissionData(permission_name);
this->grant_ = this->permission_->grantName() == permission_name;;
} else {
this->error_.reset(ts::command_result{error::parameter_missing, "permid"});
return;
}
if(this->permission_->is_invalid()) {
this->error_.reset(ts::command_result{error::parameter_invalid});
return;
}
if(kParseValue) {
if(!bulk.has("permvalue")) {
this->error_.reset(ts::command_result{error::parameter_missing, "permvalue"});
return;
}
this->value_ = bulk["permvalue"].as<permission::PermissionValue>();
this->flag_skip_ = bulk.has("permskip") && bulk["permskip"].as<bool>();
this->flag_negated_ = bulk.has("permnegated") && bulk["permnegated"].as<bool>();
}
}
PermissionBulkParser(const PermissionBulkParser&) = delete;
PermissionBulkParser(PermissionBulkParser&&) = default;
~PermissionBulkParser() {
this->error_.release_data();
}
[[nodiscard]] inline bool has_error() const {
assert(!this->error_released_);
return this->error_.has_error();
}
[[nodiscard]] inline bool has_value() const { return this->value_ != permission::undefined; }
[[nodiscard]] inline bool is_grant_permission() const { return this->grant_; }
[[nodiscard]] inline const auto& permission() const { return this->permission_; }
[[nodiscard]] inline auto permission_type() const { return this->permission_->type; }
[[nodiscard]] inline auto value() const { return this->value_; }
[[nodiscard]] inline auto flag_skip() const { return this->flag_skip_; }
[[nodiscard]] inline auto flag_negated() const { return this->flag_negated_; }
[[nodiscard]] inline ts::command_result release_error() {
assert(!std::exchange(this->error_released_, true));
return std::move(this->error_);
}
inline void emplace_custom_error(ts::command_result&& result) {
assert(!this->error_released_);
this->error_.reset(std::forward<ts::command_result>(result));
}
inline void apply_to(const std::shared_ptr<permission::v2::PermissionManager>& manager, permission::v2::PermissionUpdateType mode) const {
if(this->is_grant_permission()) {
manager->set_permission(this->permission_type(), permission::v2::empty_permission_values, permission::v2::PermissionUpdateType::do_nothing, mode);
} else {
manager->set_permission(
this->permission_type(),
{ this->value(), true },
mode,
permission::v2::PermissionUpdateType::do_nothing
);
}
}
inline void apply_to_channel(const std::shared_ptr<permission::v2::PermissionManager>& manager, permission::v2::PermissionUpdateType mode, ChannelId channel_id) const {
if(this->is_grant_permission()) {
manager->set_channel_permission(this->permission_type(), channel_id, permission::v2::empty_permission_values, permission::v2::PermissionUpdateType::do_nothing, mode);
} else {
manager->set_channel_permission(
this->permission_type(),
channel_id,
{ this->value(), true },
mode,
permission::v2::PermissionUpdateType::do_nothing
);
}
}
[[nodiscard]] inline bool is_group_property() const {
return permission_is_group_property(this->permission_type());
}
[[nodiscard]] inline bool is_client_view_property() const {
return permission_is_client_property(this->permission_type());
}
private:
std::shared_ptr<permission::PermissionTypeEntry> permission_{nullptr};
bool grant_{false};
bool flag_skip_{false};
bool flag_negated_{false};
permission::PermissionValue value_{0};
ts::command_result error_{error::ok};
#ifndef NDEBUG
bool error_released_{false};
#endif
};
template <bool kParseValue>
class PermissionBulksParser {
public:
PermissionBulksParser(const PermissionBulksParser&) = delete;
PermissionBulksParser(PermissionBulksParser&&) = default;
template <typename base_iterator>
struct FilteredPermissionIterator : public base_iterator {
public:
FilteredPermissionIterator() = default;
explicit FilteredPermissionIterator(base_iterator position, base_iterator end = {}) : base_iterator{position}, end_{end} {
if(*this != this->end_) {
const auto& entry = **this;
if(entry.has_error())
this->operator++();
}
}
FilteredPermissionIterator& operator++() {
while(true) {
base_iterator::operator++();
if(*this == this->end_) break;
const auto& entry = **this;
if(!entry.has_error()) break;
}
return *this;
}
[[nodiscard]] FilteredPermissionIterator operator++(int) const {
FilteredPermissionIterator copy = *this;
++*this;
return copy;
}
private:
base_iterator end_;
};
struct FilteredPermissionListIterable {
typedef typename std::vector<PermissionBulkParser<kParseValue>>::const_iterator const_iterator;
public:
FilteredPermissionListIterable(const_iterator begin, const_iterator end) noexcept : begin_{begin}, end_{end} {}
FilteredPermissionIterator<const_iterator> begin() const {
return FilteredPermissionIterator{this->begin_, this->end_};
}
FilteredPermissionIterator<const_iterator> end() const {
return FilteredPermissionIterator{this->end_, this->end_};
}
private:
const_iterator begin_;
const_iterator end_;
};
explicit PermissionBulksParser(ts::Command& command) {
this->permissions_.reserve(command.bulkCount());
for(size_t index{0}; index < command.bulkCount(); index++)
this->permissions_.emplace_back(command[index]);
}
[[nodiscard]] inline bool validate(const std::shared_ptr<server::ConnectedClient>& issuer, ChannelId channel_id) {
auto ignore_granted_values = permission::v2::permission_granted(1, issuer->calculate_permission(permission::b_permission_modify_power_ignore, channel_id));
if(!ignore_granted_values) {
auto max_value = issuer->calculate_permission(permission::i_permission_modify_power, channel_id, false);
if(!max_value.has_value) {
for(PermissionBulkParser<kParseValue>& permission : this->permissions_) {
if(permission.has_error()) continue;
permission.emplace_custom_error(ts::command_result{permission::i_permission_modify_power});
}
return false;
}
for(size_t index{0}; index < this->permissions_.size(); index++) {
PermissionBulkParser<kParseValue>& permission = this->permissions_[index];
if(permission.has_error()) continue;
if(kParseValue && permission_require_granted_value(permission.permission_type()) && !permission::v2::permission_granted(permission.value(), max_value)) {
permission.emplace_custom_error(ts::command_result{permission::i_permission_modify_power});
continue;
}
if(!permission::v2::permission_granted(1, issuer->calculate_permission(permission.permission_type(), channel_id, true))) {
permission.emplace_custom_error(ts::command_result{permission::i_permission_modify_power});
continue;
}
}
}
return true;
}
[[nodiscard]] inline FilteredPermissionListIterable iterate_valid_permissions() const {
return FilteredPermissionListIterable{this->permissions_.begin(), this->permissions_.end()};
}
[[nodiscard]] inline ts::command_result build_command_result() {
assert(!std::exchange(this->result_created_, true));
ts::command_result_bulk result{};
for(auto& permission : this->permissions_)
result.insert_result(std::forward<ts::command_result>(permission.release_error()));
return ts::command_result{std::move(result)};
}
private:
std::vector<PermissionBulkParser<kParseValue>> permissions_{};
#ifndef NDEBUG
bool result_created_{false};
#endif
};
}
+82 -256
View File
@@ -20,6 +20,7 @@
#include <cstdint>
#include "helpers.h"
#include "./bulk_parsers.h"
#include <Properties.h>
#include <log/LogUtils.h>
@@ -407,46 +408,16 @@ command_result ConnectedClient::handleCommandChannelGroupAddPerm(Command &cmd) {
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);
auto max_value = this->calculate_permission(permission::i_permission_modify_power, 0, false);
if(!max_value.has_value) return command_result{permission::i_permission_modify_power};
command::bulk_parser::PermissionBulksParser<true> pparser{cmd};
if(!pparser.validate(this->ref(), 0))
return pparser.build_command_result();
auto ignore_granted_values = permission::v2::permission_granted(1, this->calculate_permission(permission::b_permission_modify_power_ignore, 0));
auto conOnError = cmd[0].has("continueonerror");
bool updateList = false;
auto permission_manager = channelGroup->permissions();
for (int index = 0; index < cmd.bulkCount(); index++) {
PARSE_PERMISSION(cmd);
auto val = cmd[index]["permvalue"].as<permission::PermissionValue>();
if(!ignore_granted_values && permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) {
if(conOnError) continue;
return command_result{permission::i_permission_modify_power};
}
if(!permission::v2::permission_granted(1, this->calculate_permission(permType, 0, true))) {
if(conOnError) continue;
return command_result{permission::i_permission_modify_power};
}
if (grant) {
permission_manager->set_permission(permType, {0, cmd[index]["permvalue"]}, permission::v2::PermissionUpdateType::do_nothing, permission::v2::PermissionUpdateType::set_value);
} else {
permission_manager->set_permission(
permType,
{cmd[index]["permvalue"], 0},
permission::v2::PermissionUpdateType::set_value,
permission::v2::PermissionUpdateType::do_nothing,
cmd[index]["permskip"].as<bool>() ? 1 : 0,
cmd[index]["permnegated"].as<bool>() ? 1 : 0
);
updateList |= permission_is_group_property(permType);
}
bool updateList{false};
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
ppermission.apply_to(channelGroup->permissions(), permission::v2::PermissionUpdateType::set_value);
updateList |= ppermission.is_group_property();
}
if(updateList)
channelGroup->apply_properties_from_permissions();
@@ -465,7 +436,8 @@ command_result ConnectedClient::handleCommandChannelGroupAddPerm(Command &cmd) {
}
});
}
return command_result{error::ok};
return pparser.build_command_result();
}
command_result ConnectedClient::handleCommandChannelGroupDelPerm(Command &cmd) {
@@ -475,29 +447,14 @@ command_result ConnectedClient::handleCommandChannelGroupDelPerm(Command &cmd) {
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);
bool updateList = false;
bool conOnError = cmd[0].has("continueonerror");
command::bulk_parser::PermissionBulksParser<false> pparser{cmd};
if(!pparser.validate(this->ref(), 0))
return pparser.build_command_result();
auto permission_manager = channelGroup->permissions();
for (int index = 0; index < cmd.bulkCount(); index++) {
PARSE_PERMISSION(cmd)
if(!permission::v2::permission_granted(0, this->calculate_permission(permType, 0, true))) {
if(conOnError) continue;
return command_result{permission::i_permission_modify_power};
}
if (grant) {
permission_manager->set_permission(permType, permission::v2::empty_permission_values, permission::v2::PermissionUpdateType::do_nothing, permission::v2::PermissionUpdateType::delete_value);
} else {
permission_manager->set_permission(
permType,
permission::v2::empty_permission_values,
permission::v2::PermissionUpdateType::delete_value,
permission::v2::PermissionUpdateType::do_nothing
);
updateList |= permission_is_group_property(permType);
}
bool updateList{false};
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
ppermission.apply_to(channelGroup->permissions(), permission::v2::PermissionUpdateType::delete_value);
updateList |= ppermission.is_group_property();
}
if(updateList)
@@ -518,7 +475,8 @@ command_result ConnectedClient::handleCommandChannelGroupDelPerm(Command &cmd) {
}
});
}
return command_result{error::ok};
return pparser.build_command_result();
}
//TODO: Test if parent or previous is deleted!
@@ -1479,101 +1437,33 @@ command_result ConnectedClient::handleCommandChannelAddPerm(Command &cmd) {
ACTION_REQUIRES_CHANNEL_PERMISSION(channel, permission::i_channel_needed_permission_modify_power, permission::i_channel_permission_modify_power, true);
auto max_value = this->calculate_permission(permission::i_permission_modify_power, channel_id, false);
if(!max_value.has_value) return command_result{permission::i_permission_modify_power};
auto ignore_granted_values = permission::v2::permission_granted(1, this->calculate_permission(permission::b_permission_modify_power_ignore, channel_id));
auto updateClients = false, update_view = false, update_channel_properties = false;
bool conOnError = cmd[0].has("continueonerror");
command::bulk_parser::PermissionBulksParser<true> pparser{cmd};
if(!pparser.validate(this->ref(), channel->channelId()))
return pparser.build_command_result();
auto permission_manager = channel->permissions();
for (int index = 0; index < cmd.bulkCount(); index++) {
PARSE_PERMISSION(cmd);
auto updateClients = false, update_join_permissions = false, update_channel_properties = false;
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
ppermission.apply_to(permission_manager, permission::v2::PermissionUpdateType::set_value);
auto val = cmd[index]["permvalue"].as<permission::PermissionValue>();
if(!ignore_granted_values && permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) {
if(conOnError) continue;
return command_result{permission::i_permission_modify_power};
}
if(!permission::v2::permission_granted(1, this->calculate_permission(permType, channel_id, true))) {
if(conOnError) continue;
return command_result{permission::i_permission_modify_power};
}
if (grant) {
permission_manager->set_permission(permType, {0, cmd[index]["permvalue"]}, permission::v2::PermissionUpdateType::do_nothing, permission::v2::PermissionUpdateType::set_value);
} else {
permission_manager->set_permission(
permType,
{cmd[index]["permvalue"], 0},
permission::v2::PermissionUpdateType::set_value,
permission::v2::PermissionUpdateType::do_nothing,
cmd[index]["permskip"].as<bool>() ? 1 : 0,
cmd[index]["permnegated"].as<bool>() ? 1 : 0
);
updateClients |= permission_is_client_property(permType);
update_view |= permType == permission::i_channel_needed_view_power;
update_channel_properties |= channel->permission_require_property_update(permType);
if (permType == permission::i_icon_id) {
if(this->server) {
auto self_ref = this->ref();
this->server->forEachClient([&](std::shared_ptr<ConnectedClient> cl) {
shared_lock client_channel_lock(cl->channel_lock);
cl->notifyChannelEdited(channel, {property::CHANNEL_ICON_ID}, self_ref, false);
});
}
continue;
}
}
updateClients |= ppermission.is_client_view_property();
update_join_permissions = ppermission.permission_type() == permission::i_channel_needed_join_power;
update_channel_properties |= channel->permission_require_property_update(ppermission.permission_type());
}
/* broadcast the updated channel properties */
if(update_channel_properties) {
auto updates = channel->update_properties_from_permissions();
if(!updates.empty() && this->server){
auto self_ref = this->ref();
this->server->forEachClient([&](std::shared_ptr<ConnectedClient> cl) {
shared_lock client_channel_lock(cl->channel_lock);
cl->notifyChannelEdited(channel, updates, self_ref, false);
});
}
}
if(update_channel_properties && this->server)
this->server->update_channel_from_permissions(channel, this->ref());
if(updateClients && this->server)
for(const auto& client : this->server->getClientsByChannel(channel)) {
/* let them lock the server channel tree as well (read lock so does not matter) */
client->updateChannelClientProperties(true, true);
client->join_state_id++; /* join permission may changed, all channels need to be recalculate dif needed */
}
if(update_view && this->server) {
auto l_source = this->server->channelTree->findLinkedChannel(channel->channelId());
this->server->forEachClient([&](const shared_ptr<ConnectedClient>& cl) {
/* server tree read lock still active */
auto l_target = !cl->currentChannel ? nullptr : cl->server->channelTree->findLinkedChannel(cl->currentChannel->channelId());
sassert(l_source);
if(cl->currentChannel) sassert(l_target);
{
unique_lock client_channel_lock(cl->channel_lock);
deque<ChannelId> deleted;
for(const auto& update_entry : cl->channels->update_channel(l_source, l_target)) {
if(update_entry.first)
cl->notifyChannelShow(update_entry.second->channel(), update_entry.second->previous_channel);
else deleted.push_back(update_entry.second->channelId());
}
if(!deleted.empty())
cl->notifyChannelHide(deleted, false);
}
if((updateClients || update_join_permissions) && this->server) {
this->server->forEachClient([&](std::shared_ptr<ConnectedClient> cl) {
if(updateClients && cl->currentChannel == channel)
cl->updateChannelClientProperties(true, true);
if(update_join_permissions)
cl->join_state_id++;
});
}
return command_result{error::ok};;
return pparser.build_command_result();
}
command_result ConnectedClient::handleCommandChannelDelPerm(Command &cmd) {
@@ -1585,71 +1475,33 @@ command_result ConnectedClient::handleCommandChannelDelPerm(Command &cmd) {
ACTION_REQUIRES_CHANNEL_PERMISSION(channel, permission::i_channel_needed_permission_modify_power, permission::i_channel_permission_modify_power, true);
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");
auto updateClients = false, update_view = false, update_channel_properties = false;
command::bulk_parser::PermissionBulksParser<false> pparser{cmd};
if(!pparser.validate(this->ref(), channel->channelId()))
return pparser.build_command_result();
auto permission_manager = channel->permissions();
for (int index = 0; index < cmd.bulkCount(); index++) {
PARSE_PERMISSION(cmd);
auto updateClients = false, update_join_permissions = false, update_channel_properties = false;
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
ppermission.apply_to(permission_manager, permission::v2::PermissionUpdateType::delete_value);
if(!ignore_granted_values && !permission::v2::permission_granted(0, this->calculate_permission(permType, channel_id, true))) {
if(conOnError) continue;
return command_result{permission::i_permission_modify_power};
}
if (grant) {
permission_manager->set_permission(permType, permission::v2::empty_permission_values, permission::v2::PermissionUpdateType::do_nothing, permission::v2::PermissionUpdateType::delete_value);
} else {
permission_manager->set_permission(permType, permission::v2::empty_permission_values, permission::v2::PermissionUpdateType::delete_value, permission::v2::PermissionUpdateType::do_nothing);
updateClients |= permission_is_client_property(permType);
update_view |= permType == permission::i_channel_needed_view_power;
update_channel_properties |= channel->permission_require_property_update(permType);
}
updateClients |= ppermission.is_client_view_property();
update_join_permissions = ppermission.permission_type() == permission::i_channel_needed_join_power;
update_channel_properties |= channel->permission_require_property_update(ppermission.permission_type());
}
/* broadcast the updated channel properties */
if(update_channel_properties) {
auto updates = channel->update_properties_from_permissions();
if(!updates.empty() && this->server){
auto self_ref = this->ref();
this->server->forEachClient([&](std::shared_ptr<ConnectedClient> cl) {
shared_lock client_channel_lock(cl->channel_lock);
cl->notifyChannelEdited(channel, updates, self_ref, false);
});
}
}
if(update_channel_properties && this->server)
this->server->update_channel_from_permissions(channel, this->ref());
if(updateClients && this->server)
if((updateClients || update_join_permissions) && this->server) {
this->server->forEachClient([&](std::shared_ptr<ConnectedClient> cl) {
if(cl->currentChannel == channel) {
if(updateClients && cl->currentChannel == channel)
cl->updateChannelClientProperties(true, true);
cl->join_state_id++; /* join permission may changed, all channels need to be recalculate dif needed */
}
});
if(update_view && this->server) {
this->server->forEachClient([&](std::shared_ptr<ConnectedClient> cl) {
/* server tree read lock still active */
auto l_source = cl->server->channelTree->findLinkedChannel(channel->channelId());
auto l_target = !cl->currentChannel ? nullptr : cl->server->channelTree->findLinkedChannel(cl->currentChannel->channelId());
sassert(l_source);
if(cl->currentChannel) sassert(l_target);
{
unique_lock client_channel_lock(cl->channel_lock);
deque<ChannelId> deleted;
for(const auto& update_entry : cl->channels->update_channel(l_source, l_target)) {
if(update_entry.first)
cl->notifyChannelShow(update_entry.second->channel(), update_entry.second->previous_channel);
else deleted.push_back(update_entry.second->channelId());
}
if(!deleted.empty())
cl->notifyChannelHide(deleted, false);
}
if(update_join_permissions)
cl->join_state_id++;
});
}
return command_result{error::ok};
return pparser.build_command_result();
}
command_result ConnectedClient::handleCommandChannelClientPermList(Command &cmd) {
@@ -1728,27 +1580,21 @@ command_result ConnectedClient::handleCommandChannelClientDelPerm(Command &cmd)
ACTION_REQUIRES_PERMISSION(permission::i_client_permission_modify_power, required_permissions, channel_id);
}
bool conOnError = cmd[0].has("continueonerror"), update_view = false;
auto cll = this->server->findClientsByCldbId(cldbid);
for (int index = 0; index < cmd.bulkCount(); index++) {
PARSE_PERMISSION(cmd);
command::bulk_parser::PermissionBulksParser<false> pparser{cmd};
if(!pparser.validate(this->ref(), channel->channelId()))
return pparser.build_command_result();
if(!permission::v2::permission_granted(0, this->calculate_permission(permType, channel_id, true))) {
if(conOnError) continue;
return command_result{permission::i_permission_modify_power};
}
if (grant) {
mgr->set_channel_permission(permType, channel->channelId(), permission::v2::empty_permission_values, permission::v2::do_nothing, permission::v2::delete_value);
} else {
mgr->set_channel_permission(permType, channel->channelId(), permission::v2::empty_permission_values, permission::v2::delete_value, permission::v2::do_nothing);
update_view = permType == permission::b_channel_ignore_view_power || permType == permission::i_channel_view_power;
}
bool update_view{false};
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
ppermission.apply_to_channel(mgr, permission::v2::PermissionUpdateType::delete_value, channel->channelId());
update_view |= ppermission.is_client_view_property();
}
serverInstance->databaseHelper()->saveClientPermissions(this->server, cldbid, mgr);
if (!cll.empty()) {
for (const auto &elm : cll) {
auto onlineClients = this->server->findClientsByCldbId(cldbid);
if (!onlineClients.empty()) {
for (const auto &elm : onlineClients) {
if(elm->update_cached_permissions()) /* update cached calculated permissions */
elm->sendNeededPermissions(false); /* cached permissions had changed, notify the client */
@@ -1774,7 +1620,7 @@ command_result ConnectedClient::handleCommandChannelClientDelPerm(Command &cmd)
}
}
return command_result{error::ok};
return pparser.build_command_result();
}
command_result ConnectedClient::handleCommandChannelClientAddPerm(Command &cmd) {
@@ -1791,45 +1637,25 @@ command_result ConnectedClient::handleCommandChannelClientAddPerm(Command &cmd)
if(!channel) return command_result{error::vs_critical};
auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cldbid);
{
auto required_permissions = this->server->calculate_permission(permission::i_client_needed_permission_modify_power, cmd["cldbid"], ClientType::CLIENT_TEAMSPEAK, channel_id);
ACTION_REQUIRES_PERMISSION(permission::i_client_permission_modify_power, required_permissions, channel_id);
}
auto required_permissions = this->server->calculate_permission(permission::i_client_needed_permission_modify_power, cmd["cldbid"], ClientType::CLIENT_TEAMSPEAK, channel_id);
ACTION_REQUIRES_PERMISSION(permission::i_client_permission_modify_power, required_permissions, channel_id);
auto max_value = this->calculate_permission(permission::i_permission_modify_power, channel_id, false);
if(!max_value.has_value) return command_result{permission::i_permission_modify_power};
command::bulk_parser::PermissionBulksParser<true> pparser{cmd};
if(!pparser.validate(this->ref(), channel->channelId()))
return pparser.build_command_result();
auto ignore_granted_values = permission::v2::permission_granted(1, this->calculate_permission(permission::b_permission_modify_power_ignore, channel_id));
auto update_view = false;
bool conOnError = cmd[0].has("continueonerror");
auto onlineClientInstances = this->server->findClientsByCldbId(cldbid);
for (int index = 0; index < cmd.bulkCount(); index++) {
PARSE_PERMISSION(cmd);
auto val = cmd[index]["permvalue"].as<permission::PermissionValue>();
if(!ignore_granted_values && permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) {
if(conOnError) continue;
return command_result{permission::i_permission_modify_power};
}
if(!permission::v2::permission_granted(1, this->calculate_permission(permType, channel_id, true))) {
if(conOnError) continue;
return command_result{permission::i_permission_modify_power};
}
if (grant) {
mgr->set_channel_permission(permType, channel->channelId(), {0, cmd[index]["permvalue"]}, permission::v2::do_nothing, permission::v2::set_value);
} else {
mgr->set_channel_permission(permType, channel->channelId(), {cmd[index]["permvalue"], 0}, permission::v2::set_value, permission::v2::do_nothing, cmd[index]["permskip"] ? 1 : 0, cmd[index]["permnegated"] ? 1 : 0);
update_view = permType == permission::b_channel_ignore_view_power || permType == permission::i_channel_view_power;
}
bool update_view{false};
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
ppermission.apply_to_channel(mgr, permission::v2::PermissionUpdateType::set_value, channel->channelId());
update_view |= ppermission.is_client_view_property();
}
serverInstance->databaseHelper()->saveClientPermissions(this->server, cldbid, mgr);
if (!onlineClientInstances.empty())
for (const auto &elm : onlineClientInstances) {
auto onlineClients = this->server->findClientsByCldbId(cldbid);
if (!onlineClients.empty())
for (const auto &elm : onlineClients) {
if (elm->update_cached_permissions()) /* update cached calculated permissions */
elm->sendNeededPermissions(false); /* cached permissions had changed, notify the client */
@@ -1853,7 +1679,7 @@ command_result ConnectedClient::handleCommandChannelClientAddPerm(Command &cmd)
elm->join_state_id++; /* join permission may changed, all channels need to be recalculate dif needed */
}
return command_result{error::ok};
return pparser.build_command_result();
}
+23 -44
View File
@@ -20,6 +20,7 @@
#include <cstdint>
#include "helpers.h"
#include "./bulk_parsers.h"
#include <Properties.h>
#include <log/LogUtils.h>
@@ -241,6 +242,8 @@ command_result ConnectedClient::handleCommandClientMove(Command &cmd) {
for(auto& client : clients) {
auto oldChannel = client->getChannel();
if(!oldChannel) continue;
this->server->client_move(
client.client,
channel,
@@ -964,33 +967,17 @@ command_result ConnectedClient::handleCommandClientAddPerm(Command &cmd) {
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));
auto max_value = this->calculate_permission(permission::i_permission_modify_power, 0, false);
if(!max_value.has_value) return command_result{permission::i_permission_modify_power};
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");
auto update_channels = false;
for (int index = 0; index < cmd.bulkCount(); index++) {
PARSE_PERMISSION(cmd);
command::bulk_parser::PermissionBulksParser<true> pparser{cmd};
if(!pparser.validate(this->ref(), 0))
return pparser.build_command_result();
auto val = cmd[index]["permvalue"].as<permission::PermissionValue>();
if(!ignore_granted_values && permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) {
if(conOnError) continue;
return command_result{permission::i_permission_modify_power};
}
if(!permission::v2::permission_granted(1, this->calculate_permission(permType, 0, true))) {
if(conOnError) continue;
return command_result{permission::i_permission_modify_power};
}
if (grant) {
mgr->set_permission(permType, {0, cmd[index]["permvalue"]}, permission::v2::do_nothing, permission::v2::set_value);
} else {
mgr->set_permission(permType, {cmd[index]["permvalue"], 0}, permission::v2::set_value, permission::v2::do_nothing, cmd[index]["permskip"] ? 1 : 0, cmd[index]["permnegated"] ? 1 : 0);
update_channels |= permission_is_client_property(permType);
}
bool update_channels{false};
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
ppermission.apply_to(mgr, permission::v2::PermissionUpdateType::set_value);
update_channels |= ppermission.is_client_view_property();
}
serverInstance->databaseHelper()->saveClientPermissions(this->server, cldbid, mgr);
auto onlineClients = this->server->findClientsByCldbId(cldbid);
if (!onlineClients.empty())
@@ -1002,7 +989,7 @@ command_result ConnectedClient::handleCommandClientAddPerm(Command &cmd) {
elm->join_state_id++; /* join permission may changed, all channels need to be recalculate dif needed */
}
return command_result{error::ok};
return pparser.build_command_result();
}
command_result ConnectedClient::handleCommandClientDelPerm(Command &cmd) {
@@ -1016,36 +1003,28 @@ command_result ConnectedClient::handleCommandClientDelPerm(Command &cmd) {
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));
bool conOnError = cmd[0].has("continueonerror");
auto onlineClients = this->server->findClientsByCldbId(cmd["cldbid"]);
auto update_channel = false;
for (int index = 0; index < cmd.bulkCount(); index++) {
PARSE_PERMISSION(cmd)
command::bulk_parser::PermissionBulksParser<false> pparser{cmd};
if(!pparser.validate(this->ref(), 0))
return pparser.build_command_result();
if(!permission::v2::permission_granted(0, this->calculate_permission(permType, 0, true))) {
if(conOnError) continue;
return command_result{permission::i_permission_modify_power};
}
if (grant) {
mgr->set_permission(permType, permission::v2::empty_permission_values, permission::v2::do_nothing, permission::v2::delete_value);
} else {
mgr->set_permission(permType, permission::v2::empty_permission_values, permission::v2::delete_value, permission::v2::do_nothing);
update_channel |= permission_is_client_property(permType);
}
bool update_channels{false};
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
ppermission.apply_to(mgr, permission::v2::PermissionUpdateType::delete_value);
update_channels |= ppermission.is_client_view_property();
}
serverInstance->databaseHelper()->saveClientPermissions(this->server, cldbid, mgr);
auto onlineClients = this->server->findClientsByCldbId(cldbid);
if (!onlineClients.empty())
for (const auto &elm : onlineClients) {
if(elm->update_cached_permissions()) /* update cached calculated permissions */
elm->sendNeededPermissions(false); /* cached permissions had changed, notify the client */
if(update_channel)
if(update_channels)
elm->updateChannelClientProperties(true, true);
elm->join_state_id++; /* join permission may changed, all channels need to be recalculate dif needed */
}
return command_result{error::ok};
return pparser.build_command_result();
}
command_result ConnectedClient::handleCommandClientPermList(Command &cmd) {
+25 -88
View File
@@ -30,6 +30,7 @@
#include <StringVariable.h>
#include "helpers.h"
#include "./bulk_parsers.h"
#include <Properties.h>
#include <log/LogUtils.h>
@@ -558,35 +559,14 @@ command_result ConnectedClient::handleCommandPlaylistAddPerm(ts::Command &cmd) {
if(auto perr = playlist->client_has_permissions(this->ref(), permission::i_playlist_needed_permission_modify_power, permission::i_playlist_permission_modify_power); perr)
return command_result{perr};
auto max_value = this->calculate_permission(permission::i_permission_modify_power, 0, true);
if(!max_value.has_value) return command_result{permission::i_permission_modify_power};
command::bulk_parser::PermissionBulksParser<true> pparser{cmd};
if(!pparser.validate(this->ref(), 0))
return pparser.build_command_result();
auto ignore_granted_values = permission::v2::permission_granted(1, this->calculate_permission(permission::b_permission_modify_power_ignore, 0));
for(const auto& ppermission : pparser.iterate_valid_permissions())
ppermission.apply_to(playlist->permission_manager(), permission::v2::PermissionUpdateType::set_value);
bool conOnError = cmd[0].has("continueonerror");
for (int index = 0; index < cmd.bulkCount(); index++) {
PARSE_PERMISSION(cmd);
auto val = cmd[index]["permvalue"].as<permission::PermissionValue>();
if(permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) {
if(conOnError) continue;
return command_result{permission::i_permission_modify_power};
}
if(!ignore_granted_values && !permission::v2::permission_granted(1, this->calculate_permission(permType, 0, true))) {
if(conOnError) continue;
return command_result{permission::i_permission_modify_power};
}
if (grant) {
playlist->permission_manager()->set_permission(permType, {0, cmd[index]["permvalue"]}, permission::v2::do_nothing, permission::v2::set_value);
} else {
playlist->permission_manager()->set_permission(permType, {cmd[index]["permvalue"],0}, permission::v2::set_value, permission::v2::do_nothing, cmd[index]["permskip"].as<bool>(), cmd[index]["permnegated"].as<bool>());
}
}
return command_result{error::ok};
return pparser.build_command_result();
}
command_result ConnectedClient::handleCommandPlaylistDelPerm(ts::Command &cmd) {
@@ -600,26 +580,14 @@ command_result ConnectedClient::handleCommandPlaylistDelPerm(ts::Command &cmd) {
if(auto perr = playlist->client_has_permissions(this->ref(), permission::i_playlist_needed_permission_modify_power, permission::i_playlist_permission_modify_power); perr)
return command_result{perr};
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");
command::bulk_parser::PermissionBulksParser<false> pparser{cmd};
if(!pparser.validate(this->ref(), 0))
return pparser.build_command_result();
for (int index = 0; index < cmd.bulkCount(); index++) {
PARSE_PERMISSION(cmd);
for(const auto& ppermission : pparser.iterate_valid_permissions())
ppermission.apply_to(playlist->permission_manager(), permission::v2::PermissionUpdateType::delete_value);
if(!ignore_granted_values && !permission::v2::permission_granted(0, this->calculate_permission(permType, 0, true))) {
if(conOnError) continue;
return command_result{permission::i_permission_modify_power};
}
if (grant) {
playlist->permission_manager()->set_permission(permType, {0, 0}, permission::v2::do_nothing, permission::v2::delete_value);
} else {
playlist->permission_manager()->set_permission(permType, {0, 0}, permission::v2::delete_value, permission::v2::do_nothing);
}
}
return command_result{error::ok};
return pparser.build_command_result();
}
command_result ConnectedClient::handleCommandPlaylistClientList(ts::Command &cmd) {
@@ -735,34 +703,14 @@ command_result ConnectedClient::handleCommandPlaylistClientAddPerm(ts::Command &
if(auto perr = playlist->client_has_permissions(this->ref(), permission::i_playlist_needed_permission_modify_power, permission::i_playlist_permission_modify_power); perr)
return command_result{perr};
auto max_value = this->calculate_permission(permission::i_permission_modify_power, 0, true);
if(!max_value.has_value) return command_result{permission::i_permission_modify_power};
command::bulk_parser::PermissionBulksParser<true> pparser{cmd};
if(!pparser.validate(this->ref(), this->getClientDatabaseId()))
return pparser.build_command_result();
auto ignore_granted_values = permission::v2::permission_granted(1, this->calculate_permission(permission::b_permission_modify_power_ignore, 0));
for(const auto& ppermission : pparser.iterate_valid_permissions())
ppermission.apply_to_channel(playlist->permission_manager(), permission::v2::PermissionUpdateType::set_value, client_id);
bool conOnError = cmd[0].has("continueonerror");
for (int index = 0; index < cmd.bulkCount(); index++) {
PARSE_PERMISSION(cmd);
auto val = cmd[index]["permvalue"].as<permission::PermissionValue>();
if(permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) {
if(conOnError) continue;
return command_result{permission::i_permission_modify_power};
}
if(!ignore_granted_values && !permission::v2::permission_granted(1, this->calculate_permission(permType, 0, true))) {
if(conOnError) continue;
return command_result{permission::i_permission_modify_power};
}
if (grant) {
playlist->permission_manager()->set_channel_permission(permType, client_id, {0, cmd[index]["permvalue"]}, permission::v2::do_nothing, permission::v2::set_value);
} else {
playlist->permission_manager()->set_channel_permission(permType, client_id, {cmd[index]["permvalue"], 0}, permission::v2::set_value, permission::v2::do_nothing, cmd[index]["permskip"].as<bool>(), cmd[index]["permnegated"].as<bool>());
}
}
return command_result{error::ok};
return pparser.build_command_result();
}
command_result ConnectedClient::handleCommandPlaylistClientDelPerm(ts::Command &cmd) {
@@ -779,26 +727,15 @@ command_result ConnectedClient::handleCommandPlaylistClientDelPerm(ts::Command &
if(auto perr = playlist->client_has_permissions(this->ref(), permission::i_playlist_needed_permission_modify_power, permission::i_playlist_permission_modify_power); perr)
return command_result{perr};
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");
for (int index = 0; index < cmd.bulkCount(); index++) {
PARSE_PERMISSION(cmd);
command::bulk_parser::PermissionBulksParser<false> pparser{cmd};
if(!pparser.validate(this->ref(), this->getClientDatabaseId()))
return pparser.build_command_result();
if(!ignore_granted_values && !permission::v2::permission_granted(0, this->calculate_permission(permType, 0, true))) {
if(conOnError) continue;
return command_result{permission::i_permission_modify_power};
}
for(const auto& ppermission : pparser.iterate_valid_permissions())
ppermission.apply_to_channel(playlist->permission_manager(), permission::v2::PermissionUpdateType::delete_value, client_id);
if (grant) {
playlist->permission_manager()->set_channel_permission(permType, client_id, {0, 0}, permission::v2::do_nothing, permission::v2::delete_value);
} else {
playlist->permission_manager()->set_channel_permission(permType, client_id, {0, 0}, permission::v2::delete_value, permission::v2::do_nothing);
}
}
return command_result{error::ok};
return pparser.build_command_result();
}
constexpr auto max_song_meta_info = 1024 * 512;
+61 -164
View File
@@ -4,9 +4,6 @@
#include <memory>
#include <spdlog/sinks/rotating_file_sink.h>
#include <iostream>
#include <bitset>
#include <algorithm>
#include <openssl/sha.h>
@@ -16,7 +13,6 @@
#include "src/server/file/LocalFileServer.h"
#include "../../server/VoiceServer.h"
#include "../voice/VoiceClient.h"
#include "PermissionManager.h"
#include "../../InstanceHandler.h"
#include "../../server/QueryServer.h"
#include "../file/FileClient.h"
@@ -25,25 +21,17 @@
#include "../../weblist/WebListManager.h"
#include "../../manager/ConversationManager.h"
#include "../../manager/PermissionNameMapper.h"
#include <experimental/filesystem>
#include <cstdint>
#include <StringVariable.h>
#include "helpers.h"
#include "./bulk_parsers.h"
#include <Properties.h>
#include <log/LogUtils.h>
#include <misc/sassert.h>
#include <misc/base64.h>
#include <misc/hex.h>
#include <misc/digest.h>
#include <misc/rnd.h>
#include <misc/timer.h>
#include <misc/strobf.h>
#include <misc/scope_guard.h>
#include <bbcode/bbcodes.h>
namespace fs = std::experimental::filesystem;
using namespace std::chrono;
using namespace std;
using namespace ts;
@@ -805,73 +793,43 @@ command_result ConnectedClient::handleCommandServerGroupAddPerm(Command &cmd) {
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_serverinstance_modify_templates, 1);
}
command::bulk_parser::PermissionBulksParser<true> pparser{cmd};
if(!pparser.validate(this->ref(), 0))
return pparser.build_command_result();
auto max_value = this->calculate_permission(permission::i_permission_modify_power, 0, false);
if(!max_value.has_value) return command_result{permission::i_permission_modify_power};
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 checkTp = false;
bool sgroupUpdate = false;
bool update_talk_power{false}, update_server_group_list{false};
auto permissions = serverGroup->permissions();
for (int index = 0; index < cmd.bulkCount(); index++) {
PARSE_PERMISSION(cmd);
//permvalue='1' permnegated='0' permskip='0'
auto val = cmd[index]["permvalue"].as<permission::PermissionValue>();
if(!ignore_granted_values && permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) {
if(conOnError) continue;
return command_result{permission::i_permission_modify_power};
}
if(!permission::v2::permission_granted(1, this->calculate_permission(permType, 0, true))) {
if(conOnError) continue;
return command_result{permission::i_permission_modify_power};
}
if (grant) {
permissions->set_permission(permType, {0, cmd[index]["permvalue"]}, permission::v2::PermissionUpdateType::do_nothing, permission::v2::PermissionUpdateType::set_value);
} else {
permissions->set_permission(
permType,
{cmd[index]["permvalue"], 0},
permission::v2::PermissionUpdateType::set_value,
permission::v2::PermissionUpdateType::do_nothing,
cmd[index]["permskip"].as<bool>() ? 1 : 0,
cmd[index]["permnegated"].as<bool>() ? 1 : 0
);
sgroupUpdate |= permission_is_group_property(permType);
checkTp |= permission_is_client_property(permType);
}
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
ppermission.apply_to(serverGroup->permissions(), permission::v2::PermissionUpdateType::set_value);
update_server_group_list |= ppermission.is_group_property();
update_talk_power |= ppermission.is_client_view_property();
}
if(sgroupUpdate)
if(update_server_group_list)
serverGroup->apply_properties_from_permissions();
//TODO may update for every server?
if(this->server) {
auto lock = this->_this.lock();
auto server = this->server;
threads::Thread([checkTp, sgroupUpdate, serverGroup, lock, server]() {
if(sgroupUpdate)
threads::Thread([update_talk_power, update_server_group_list, serverGroup, lock, server]() {
if(update_server_group_list)
server->forEachClient([](shared_ptr<ConnectedClient> cl) {
cl->notifyServerGroupList();
});
server->forEachClient([serverGroup, checkTp](shared_ptr<ConnectedClient> cl) {
server->forEachClient([serverGroup, update_talk_power](shared_ptr<ConnectedClient> cl) {
if (cl->serverGroupAssigned(serverGroup)) {
if(cl->update_cached_permissions()) /* update cached calculated permissions */
cl->sendNeededPermissions(false); /* cached permissions had changed, notify the client */
if (checkTp)
if (update_talk_power)
cl->updateChannelClientProperties(true, true);
cl->join_state_id++; /* join permission may changed, all channels need to be recalculate dif needed */
}
});
}).detach();
}
return command_result{error::ok};
return pparser.build_command_result();
}
command_result ConnectedClient::handleCommandServerGroupDelPerm(Command &cmd) {
@@ -890,49 +848,34 @@ command_result ConnectedClient::handleCommandServerGroupDelPerm(Command &cmd) {
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_serverinstance_modify_templates, 1);
}
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 checkTp = false;
auto sgroupUpdate = false;
for (int index = 0; index < cmd.bulkCount(); index++) {
PARSE_PERMISSION(cmd);
command::bulk_parser::PermissionBulksParser<false> pparser{cmd};
if(!pparser.validate(this->ref(), 0))
return pparser.build_command_result();
if(!ignore_granted_values && !permission::v2::permission_granted(0, this->calculate_permission(permType, 0, true))) {
if(conOnError) continue;
return command_result{permission::i_permission_modify_power};
}
if (grant) {
serverGroup->permissions()->set_permission(permType, permission::v2::empty_permission_values, permission::v2::PermissionUpdateType::do_nothing, permission::v2::PermissionUpdateType::delete_value);
} else {
serverGroup->permissions()->set_permission(
permType,
permission::v2::empty_permission_values,
permission::v2::PermissionUpdateType::delete_value,
permission::v2::PermissionUpdateType::do_nothing
);
sgroupUpdate |= permission_is_group_property(permType);
checkTp |= permission_is_client_property(permType);
}
bool update_talk_power{false}, update_server_group_list{false};
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
ppermission.apply_to(serverGroup->permissions(), permission::v2::PermissionUpdateType::delete_value);
update_server_group_list |= ppermission.is_group_property();
update_talk_power |= ppermission.is_client_view_property();
}
if(sgroupUpdate)
if(update_server_group_list)
serverGroup->apply_properties_from_permissions();
if(this->server) {
auto lock = this->_this.lock();
auto server = this->server;
threads::Thread([checkTp, sgroupUpdate, serverGroup, lock, server]() {
if(sgroupUpdate)
threads::Thread([update_talk_power, update_server_group_list, serverGroup, lock, server]() {
if(update_server_group_list)
server->forEachClient([](shared_ptr<ConnectedClient> cl) {
cl->notifyServerGroupList();
});
server->forEachClient([serverGroup, checkTp](shared_ptr<ConnectedClient> cl) {
server->forEachClient([serverGroup, update_talk_power](shared_ptr<ConnectedClient> cl) {
if (cl->serverGroupAssigned(serverGroup)) {
if(cl->update_cached_permissions()) /* update cached calculated permissions */
cl->sendNeededPermissions(false); /* cached permissions had changed, notify the client */
if (checkTp)
if (update_talk_power)
cl->updateChannelClientProperties(true, true);
cl->join_state_id++; /* join permission may changed, all channels need to be recalculate dif needed */
}
@@ -940,7 +883,7 @@ command_result ConnectedClient::handleCommandServerGroupDelPerm(Command &cmd) {
}).detach();
}
return command_result{error::ok};
return pparser.build_command_result();
}
command_result ConnectedClient::handleCommandServerGroupAutoAddPerm(ts::Command& cmd) {
@@ -970,67 +913,37 @@ command_result ConnectedClient::handleCommandServerGroupAutoAddPerm(ts::Command&
if(groups.empty())
return command_result{error::ok};
auto max_value = this->calculate_permission(permission::i_permission_modify_power, 0, false);
if(!max_value.has_value) return command_result{permission::i_permission_modify_power};
command::bulk_parser::PermissionBulksParser<true> pparser{cmd};
if(!pparser.validate(this->ref(), 0))
return pparser.build_command_result();
auto ignore_granted_values = permission::v2::permission_granted(1, this->calculate_permission(permission::b_permission_modify_power_ignore, 0));
bool update_clients{false}, update_server_group_list{false};
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
for(const auto& serverGroup : groups)
ppermission.apply_to(serverGroup->permissions(), permission::v2::PermissionUpdateType::set_value);
bool conOnError = cmd[0].has("continueonerror");
bool checkTp = false;
bool sgroupUpdate = false;
for (int index = 0; index < cmd.bulkCount(); index++) {
PARSE_PERMISSION(cmd);
//permvalue='1' permnegated='0' permskip='0'end
auto val = cmd[index]["permvalue"].as<permission::PermissionValue>();
if(permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) {
if(conOnError) continue;
return command_result{permission::i_permission_modify_power};
}
if(!ignore_granted_values && !permission::v2::permission_granted(1, this->calculate_permission(permType, 0, true))) {
if(conOnError) continue;
return command_result{permission::i_permission_modify_power};
}
for(const auto& serverGroup : groups) {
if (grant) {
serverGroup->permissions()->set_permission(permType, {0, cmd[index]["permvalue"]}, permission::v2::PermissionUpdateType::do_nothing, permission::v2::PermissionUpdateType::set_value);
} else {
serverGroup->permissions()->set_permission(
permType,
{cmd[index]["permvalue"], 0},
permission::v2::PermissionUpdateType::set_value,
permission::v2::PermissionUpdateType::do_nothing,
cmd[index]["permskip"].as<bool>() ? 1 : 0,
cmd[index]["permnegated"].as<bool>() ? 1 : 0
);
}
}
sgroupUpdate |= permission_is_group_property(permType);
checkTp |= permission_is_client_property(permType);
update_server_group_list |= ppermission.is_group_property();
update_clients |= ppermission.is_client_view_property();
}
if(sgroupUpdate)
if(update_server_group_list)
for(auto& group : groups)
group->apply_properties_from_permissions();
auto lock = this->_this.lock();
if(ref_server) {
threads::Thread([checkTp, sgroupUpdate, groups, lock, ref_server]() {
if(sgroupUpdate)
threads::Thread([update_clients, update_server_group_list, groups, lock, ref_server]() {
if(update_server_group_list)
ref_server->forEachClient([](shared_ptr<ConnectedClient> cl) {
cl->notifyServerGroupList();
});
ref_server->forEachClient([groups, checkTp](shared_ptr<ConnectedClient> cl) {
ref_server->forEachClient([groups, update_clients](shared_ptr<ConnectedClient> cl) {
for(const auto& serverGroup : groups) {
if (cl->serverGroupAssigned(serverGroup)) {
if(cl->update_cached_permissions()) {/* update cached calculated permissions */
cl->sendNeededPermissions(false); /* cached permissions had changed, notify the client */
}
if (checkTp) {
if (update_clients) {
cl->updateChannelClientProperties(true, true);
}
cl->join_state_id++; /* join permission may changed, all channels need to be recalculate if needed */
@@ -1040,7 +953,8 @@ command_result ConnectedClient::handleCommandServerGroupAutoAddPerm(ts::Command&
});
}).detach();
}
return command_result{error::ok};
return pparser.build_command_result();
}
command_result ConnectedClient::handleCommandServerGroupAutoDelPerm(ts::Command& cmd) {
@@ -1069,54 +983,37 @@ command_result ConnectedClient::handleCommandServerGroupAutoDelPerm(ts::Command&
if(groups.empty()) return command_result{error::ok};
auto ignore_granted_values = permission::v2::permission_granted(1, this->calculate_permission(permission::b_permission_modify_power_ignore, 0));
command::bulk_parser::PermissionBulksParser<false> pparser{cmd};
if(!pparser.validate(this->ref(), 0))
return pparser.build_command_result();
bool conOnError = cmd[0].has("continueonerror");
bool checkTp = false;
auto sgroupUpdate = false;
for (int index = 0; index < cmd.bulkCount(); index++) {
PARSE_PERMISSION(cmd);
bool update_clients{false}, update_server_group_list{false};
for(const auto& ppermission : pparser.iterate_valid_permissions()) {
for(const auto& serverGroup : groups)
ppermission.apply_to(serverGroup->permissions(), permission::v2::PermissionUpdateType::delete_value);
if(!ignore_granted_values && !permission::v2::permission_granted(0, this->calculate_permission(permType, 0, true))) {
if(conOnError) continue;
return command_result{permission::i_permission_modify_power};
}
for(const auto& serverGroup : groups) {
if (grant) {
serverGroup->permissions()->set_permission(permType, permission::v2::empty_permission_values, permission::v2::PermissionUpdateType::do_nothing, permission::v2::PermissionUpdateType::delete_value);
} else {
serverGroup->permissions()->set_permission(
permType,
permission::v2::empty_permission_values,
permission::v2::PermissionUpdateType::delete_value,
permission::v2::PermissionUpdateType::do_nothing
);
sgroupUpdate |= permission_is_group_property(permType);
}
}
checkTp |= permission_is_client_property(permType);
update_server_group_list |= ppermission.is_group_property();
update_clients |= ppermission.is_client_view_property();
}
if(sgroupUpdate) {
if(update_server_group_list) {
for(auto& group : groups)
group->apply_properties_from_permissions();
}
if(ref_server) {
auto lock = this->_this.lock();
threads::Thread([checkTp, sgroupUpdate, groups, lock, ref_server]() {
if(sgroupUpdate)
threads::Thread([update_clients, update_server_group_list, groups, lock, ref_server]() {
if(update_server_group_list)
ref_server->forEachClient([](shared_ptr<ConnectedClient> cl) {
cl->notifyServerGroupList();
});
ref_server->forEachClient([groups, checkTp](shared_ptr<ConnectedClient> cl) {
ref_server->forEachClient([groups, update_clients](shared_ptr<ConnectedClient> cl) {
for(const auto& serverGroup : groups) {
if (cl->serverGroupAssigned(serverGroup)) {
if(cl->update_cached_permissions()) /* update cached calculated permissions */
cl->sendNeededPermissions(false); /* cached permissions had changed, notify the client */
if (checkTp)
if (update_clients)
cl->updateChannelClientProperties(true, true);
cl->join_state_id++; /* join permission may changed, all channels need to be recalculate dif needed */
break;
@@ -1126,7 +1023,7 @@ command_result ConnectedClient::handleCommandServerGroupAutoDelPerm(ts::Command&
}).detach();
}
return command_result{error::ok};
return pparser.build_command_result();
}
command_result ConnectedClient::handleCommandServerGroupsByClientId(Command &cmd) {