A lot of updates
This commit is contained in:
@@ -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
|
||||
};
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user