Using new permissions system consequently
This commit is contained in:
@@ -85,20 +85,20 @@ void ConnectedClient::updateChannelClientProperties(bool lock_channel_tree, bool
|
||||
/* this->server may be null! */
|
||||
shared_ptr<TSServer> server_ref = this->server;
|
||||
|
||||
auto permissions = this->permissionValues(permission::PERMTEST_ORDERED, {
|
||||
auto permissions = this->calculate_permissions({
|
||||
permission::i_client_talk_power,
|
||||
permission::b_client_is_priority_speaker,
|
||||
permission::b_client_ignore_antiflood,
|
||||
permission::i_channel_view_power,
|
||||
permission::b_channel_ignore_view_power
|
||||
}, this->currentChannel);
|
||||
}, this->currentChannel ? this->currentChannel->channelId() : 0);
|
||||
|
||||
permission::PermissionValue
|
||||
permission_talk_power = permNotGranted,
|
||||
permission_priority_speaker = permNotGranted,
|
||||
permission_ignore_antiflood = permNotGranted,
|
||||
permission_channel_view_power = permNotGranted,
|
||||
permission_channel_ignore_view_power = permNotGranted;
|
||||
permission::v2::PermissionFlaggedValue
|
||||
permission_talk_power{0, false},
|
||||
permission_priority_speaker{0, false},
|
||||
permission_ignore_antiflood{0, false},
|
||||
permission_channel_view_power{0, false},
|
||||
permission_channel_ignore_view_power{0, false};
|
||||
for(const auto& perm : permissions) {
|
||||
if(perm.first == permission::i_client_talk_power)
|
||||
permission_talk_power = perm.second;
|
||||
@@ -113,18 +113,15 @@ void ConnectedClient::updateChannelClientProperties(bool lock_channel_tree, bool
|
||||
else sassert(false);
|
||||
}
|
||||
|
||||
if(permission_talk_power < -2) permission_talk_power = -2;
|
||||
else if(permission_talk_power == -2) permission_talk_power = 0;
|
||||
|
||||
deque<property::ClientProperties> notifyList;
|
||||
debugMessage(this->getServerId(), "{} Got a channel talk power of {} Talk power set is {}", CLIENT_STR_LOG_PREFIX, permission_talk_power, this->properties()[property::CLIENT_TALK_POWER].as<uint64_t>());
|
||||
if(permission_talk_power != this->properties()[property::CLIENT_TALK_POWER].as<uint64_t>()) { //We do not have to update tp if there's no channel
|
||||
this->properties()[property::CLIENT_TALK_POWER] = permission_talk_power;
|
||||
if((permission_talk_power.has_value ? permission_talk_power.value : 0) != this->properties()[property::CLIENT_TALK_POWER].as<uint64_t>()) { //We do not have to update tp if there's no channel
|
||||
this->properties()[property::CLIENT_TALK_POWER] = (permission_talk_power.has_value ? permission_talk_power.value : 0);
|
||||
notifyList.emplace_back(property::CLIENT_TALK_POWER);
|
||||
|
||||
auto update = this->properties()[property::CLIENT_IS_TALKER].as<bool>() || this->properties()[property::CLIENT_TALK_REQUEST].as<int64_t>() > 0;
|
||||
if(update && this->currentChannel) {
|
||||
if(this->currentChannel->talk_power_granted({permission_talk_power, permission_talk_power != permNotGranted})) {
|
||||
if(this->currentChannel->talk_power_granted(permission_talk_power)) {
|
||||
this->properties()[property::CLIENT_IS_TALKER] = 0;
|
||||
this->properties()[property::CLIENT_TALK_REQUEST] = 0;
|
||||
this->properties()[property::CLIENT_TALK_REQUEST_MSG] = "";
|
||||
@@ -164,16 +161,16 @@ void ConnectedClient::updateChannelClientProperties(bool lock_channel_tree, bool
|
||||
}
|
||||
}
|
||||
|
||||
auto pSpeaker = permission_priority_speaker > 0;
|
||||
auto pSpeaker = permission_priority_speaker.has_value && permission_priority_speaker.value > 0;
|
||||
if(properties()[property::CLIENT_IS_PRIORITY_SPEAKER].as<bool>() != pSpeaker){
|
||||
properties()[property::CLIENT_IS_PRIORITY_SPEAKER] = pSpeaker;
|
||||
notifyList.emplace_back(property::CLIENT_IS_PRIORITY_SPEAKER);
|
||||
}
|
||||
|
||||
block_flood = permission_ignore_antiflood <= 0 || permission_ignore_antiflood == permNotGranted;
|
||||
block_flood = !!permission_ignore_antiflood.has_value || permission_ignore_antiflood.value <= 0;
|
||||
if(server_ref)
|
||||
server_ref->notifyClientPropertyUpdates(_this.lock(), notifyList, notify_self);
|
||||
this->updateTalkRights(permission_talk_power);
|
||||
this->updateTalkRights(permission_talk_power.has_value ? permission_talk_power.value : 0);
|
||||
|
||||
if((this->channels_view_power != permission_channel_view_power || this->channels_ignore_view != permission_channel_ignore_view_power) && notify_self && this->currentChannel && server_ref) {
|
||||
this->channels_view_power = permission_channel_view_power;
|
||||
@@ -229,7 +226,7 @@ std::deque<std::shared_ptr<BasicChannel>> ConnectedClient::subscribeChannel(cons
|
||||
if(!ref_server)
|
||||
return {};
|
||||
|
||||
auto general_granted = enforce || this->permission_granted(this->permissionValue(permission::b_channel_ignore_subscribe_power, nullptr), 1, true);
|
||||
auto general_granted = enforce || permission::v2::permission_granted(1, this->calculate_permission(permission::b_channel_ignore_subscribe_power, 0));
|
||||
{
|
||||
shared_lock server_channel_lock(ref_server->channel_tree_lock, defer_lock);
|
||||
unique_lock client_channel_lock(this->channel_lock, defer_lock);
|
||||
@@ -245,10 +242,10 @@ std::deque<std::shared_ptr<BasicChannel>> ConnectedClient::subscribeChannel(cons
|
||||
if(local_channel->subscribed) continue; //Already subscribed
|
||||
|
||||
if(!general_granted && channel != this->currentChannel) {
|
||||
auto granted_permission = this->calculate_permission_value(permission::i_channel_subscribe_power, channel->channelId());
|
||||
auto granted_permission = this->calculate_permission(permission::i_channel_subscribe_power, channel->channelId());
|
||||
|
||||
if(!channel->permission_granted(permission::i_channel_needed_subscribe_power, granted_permission, false)) {
|
||||
auto ignore_power = this->calculate_permission_value(permission::b_channel_ignore_subscribe_power, channel->channelId());
|
||||
auto ignore_power = this->calculate_permission(permission::b_channel_ignore_subscribe_power, channel->channelId());
|
||||
if(!ignore_power.has_value || ignore_power.value < 1)
|
||||
continue;
|
||||
}
|
||||
@@ -564,9 +561,9 @@ bool ConnectedClient::notifyClientNeededPermissions() {
|
||||
cache_lock.unlock();
|
||||
|
||||
for(const auto& value : permissions) {
|
||||
if(value.second != permNotGranted || value.first == permission::b_client_force_push_to_talk) {
|
||||
if(value.second.has_value) {
|
||||
cmd[index]["permid"] = value.first;
|
||||
cmd[index++]["permvalue"] = value.second == permNotGranted ? 0 : value.second;
|
||||
cmd[index++]["permvalue"] = value.second.value;
|
||||
}
|
||||
}
|
||||
if(permissions.empty()) {
|
||||
@@ -591,6 +588,8 @@ bool ConnectedClient::notifyError(const command_result& result, const std::strin
|
||||
} else {
|
||||
cmd["id"] = (int) result.error_code();
|
||||
cmd["msg"] = findError(result.error_code()).message;
|
||||
if(result.is_permission_error())
|
||||
cmd["failed_permid"] = result.permission_id();
|
||||
}
|
||||
|
||||
if(retCode.length() > 0)
|
||||
@@ -616,7 +615,7 @@ inline void send_channels(ConnectedClient* client, ChannelIT begin, const Channe
|
||||
if(begin == end)
|
||||
return;
|
||||
|
||||
Command channellist("channellist");
|
||||
ts::command_builder builder{"channellist", 512, 6};
|
||||
size_t index = 0;
|
||||
|
||||
while(begin != end) {
|
||||
@@ -625,9 +624,9 @@ inline void send_channels(ConnectedClient* client, ChannelIT begin, const Channe
|
||||
|
||||
for (const auto &elm : channel->properties().list_properties(property::FLAG_CHANNEL_VIEW, client->getType() == CLIENT_TEAMSPEAK ? property::FLAG_NEW : (uint16_t) 0)) {
|
||||
if(elm.type() == property::CHANNEL_ORDER)
|
||||
channellist[index][elm.type().name] = override_orderid ? 0 : (*begin)->previous_channel;
|
||||
builder.put_unchecked(index, elm.type().name, override_orderid ? 0 : (*begin)->previous_channel);
|
||||
else
|
||||
channellist[index][elm.type().name] = elm.as<string>();
|
||||
builder.put_unchecked(index, elm.type().name, elm.as<string>());
|
||||
}
|
||||
|
||||
begin++;
|
||||
@@ -636,9 +635,9 @@ inline void send_channels(ConnectedClient* client, ChannelIT begin, const Channe
|
||||
}
|
||||
if(dynamic_cast<VoiceClient*>(client)) {
|
||||
auto vc = dynamic_cast<VoiceClient*>(client);
|
||||
vc->sendCommand0(channellist, false, true); /* we need to process this command directly so it will be processed before the channellistfinished stuff */
|
||||
vc->sendCommand0(builder.build(), false, true); /* we need to process this command directly so it will be processed before the channellistfinished stuff */
|
||||
} else {
|
||||
client->sendCommand(channellist);
|
||||
client->sendCommand(builder);
|
||||
}
|
||||
if(begin != end)
|
||||
send_channels(client, begin, end, override_orderid);
|
||||
@@ -785,7 +784,7 @@ void ConnectedClient::sendServerInit() {
|
||||
command["acn"] = this->getDisplayName();
|
||||
command["aclid"] = this->getClientId();
|
||||
if(dynamic_cast<VoiceClient*>(this)) {
|
||||
dynamic_cast<VoiceClient*>(this)->sendCommand0(command, false, true); /* process it directly so the order for the channellist entries is ensured. (First serverinit then everything else) */
|
||||
dynamic_cast<VoiceClient*>(this)->sendCommand0(command.build(), false, true); /* process it directly so the order for the channellist entries is ensured. (First serverinit then everything else) */
|
||||
} else {
|
||||
this->sendCommand(command);
|
||||
}
|
||||
@@ -851,7 +850,7 @@ bool ConnectedClient::handleCommandFull(Command& cmd, bool disconnectOnFail) {
|
||||
}
|
||||
|
||||
std::shared_ptr<BanRecord> ConnectedClient::resolveActiveBan(const std::string& ip_address) {
|
||||
if(this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_client_ignore_bans, 1)) return nullptr;
|
||||
if(permission::v2::permission_granted(1, this->calculate_permission(permission::b_client_ignore_bans, 0))) return nullptr;
|
||||
|
||||
//Check if manager banned
|
||||
auto banManager = serverInstance->banManager();
|
||||
@@ -901,44 +900,37 @@ std::shared_ptr<BanRecord> ConnectedClient::resolveActiveBan(const std::string&
|
||||
}
|
||||
|
||||
bool ConnectedClient::update_cached_permissions() {
|
||||
auto values = this->permissionValues(permission::PERMTEST_ORDERED, permission::neededPermissions, shared_ptr(this->currentChannel)); /* copy the channel here so it does not change */
|
||||
auto values = this->calculate_permissions(permission::neededPermissions, this->currentChannel? this->currentChannel->channelId() : 0); /* copy the channel here so it does not change */
|
||||
auto updated = false;
|
||||
|
||||
|
||||
{
|
||||
lock_guard cached_lock(this->cached_permissions_lock);
|
||||
|
||||
vector<permission::PermissionType> old_permissions;
|
||||
old_permissions.reserve(this->cached_permissions.size());
|
||||
auto old_cached_permissions{this->cached_permissions};
|
||||
this->cached_permissions = values;
|
||||
std::sort(this->cached_permissions.begin(), this->cached_permissions.end(), [](const auto& a, const auto& b) { return a.first < b.first; });
|
||||
|
||||
for(const auto& value : this->cached_permissions)
|
||||
old_permissions.push_back(value.first);
|
||||
|
||||
for(const auto& value : values) {
|
||||
auto value_it = cached_permissions.find(value.first);
|
||||
if(value_it == cached_permissions.end()) { /* new entry */
|
||||
updated = true;
|
||||
this->cached_permissions[value.first] = value.second;
|
||||
continue; /* no need to remove that from old_permissions because it isn't there */
|
||||
} else if(value_it->second != value.second) { /* entry changed */
|
||||
updated = true;
|
||||
value_it->second = value.second;
|
||||
}
|
||||
|
||||
{ /* we've updated the value or verified it */
|
||||
auto old_it = find(old_permissions.begin(), old_permissions.end(), value.first);
|
||||
if(old_it != old_permissions.end())
|
||||
old_permissions.erase(old_it);
|
||||
if(this->cached_permissions.size() != old_cached_permissions.size())
|
||||
updated = true;
|
||||
else {
|
||||
for(auto oit = old_cached_permissions.begin(), nit = this->cached_permissions.begin(); oit != old_cached_permissions.end(); oit++, nit++) {
|
||||
if(oit->first != nit->first || oit->second != nit->second) {
|
||||
updated = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(const auto& left : old_permissions) {
|
||||
auto value_it = cached_permissions.find(left);
|
||||
if(value_it != cached_permissions.end()) {
|
||||
cached_permissions.erase(value_it);
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
this->cpmerission_whisper_power = {0, false};
|
||||
this->cpmerission_needed_whisper_power = {0, false};
|
||||
for(const auto& entry : values) {
|
||||
if(entry.first == permission::i_client_whisper_power)
|
||||
this->cpmerission_whisper_power = entry.second;
|
||||
else
|
||||
if(entry.first == permission::i_client_needed_whisper_power)
|
||||
this->cpmerission_needed_whisper_power = entry.second;
|
||||
}
|
||||
|
||||
return updated;
|
||||
@@ -954,72 +946,47 @@ void ConnectedClient::sendTSPermEditorWarning() {
|
||||
}
|
||||
}
|
||||
|
||||
permission::v2::PermissionFlaggedValue ConnectedClient::calculate_permission_value(const ts::permission::PermissionType &permission, ts::ChannelId channel_id) {
|
||||
if(channel_id == (this->currentChannel ? this->currentChannel->channelId() : 0) || channel_id == -1) {
|
||||
std::lock_guard lock(this->cached_permissions_lock);
|
||||
auto index = this->cached_permissions.find(permission);
|
||||
if(index != this->cached_permissions.end())
|
||||
return {index->second, index->second != permNotGranted};
|
||||
}
|
||||
|
||||
auto ref_server = this->server;
|
||||
if(ref_server) {
|
||||
auto result = this->server->calculatePermissions2(this->getClientDatabaseId(), {permission}, this->getType(), channel_id, false);
|
||||
if(!result.empty()) /* it should never be empty! */
|
||||
return result.back().second;
|
||||
}
|
||||
|
||||
auto value = this->permissionValue(permission::PERMTEST_ORDERED, permission, nullptr);
|
||||
return {value, value != permNotGranted};
|
||||
}
|
||||
|
||||
#define RESULT(flag) \
|
||||
#define RESULT(perm_) \
|
||||
do { \
|
||||
ventry->join_state_id = this->join_state_id; \
|
||||
ventry->joinable = (flag); \
|
||||
return flag; \
|
||||
ventry->join_permission_error = (perm_); \
|
||||
return perm_; \
|
||||
} while(0)
|
||||
|
||||
bool ConnectedClient::calculate_and_get_join_state(const std::shared_ptr<BasicChannel>& channel) {
|
||||
permission::PermissionType ConnectedClient::calculate_and_get_join_state(const std::shared_ptr<BasicChannel>& channel) {
|
||||
shared_ptr<ViewEntry> ventry;
|
||||
{
|
||||
shared_lock view_lock(this->channel_lock);
|
||||
ventry = this->channel_view()->find_channel(channel);
|
||||
if(!ventry)
|
||||
return false;
|
||||
return permission::i_channel_view_power;
|
||||
}
|
||||
if(ventry->join_state_id == this->join_state_id)
|
||||
return ventry->joinable;
|
||||
return ventry->join_permission_error;
|
||||
|
||||
auto channel_id = channel->channelId();
|
||||
auto permission_cache = make_shared<CalculateCache>();
|
||||
switch(channel->channelType()) {
|
||||
case ChannelType::permanent:
|
||||
if(!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_channel_join_permanent, 1, channel, true, permission_cache))
|
||||
RESULT(false);
|
||||
if(!permission::v2::permission_granted(1, this->calculate_permission(permission::b_channel_join_permanent, channel_id)))
|
||||
RESULT(permission::b_channel_join_permanent);
|
||||
break;
|
||||
case ChannelType::semipermanent:
|
||||
if(!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_channel_join_semi_permanent, 1, channel, true, permission_cache))
|
||||
RESULT(false);
|
||||
if(!permission::v2::permission_granted(1, this->calculate_permission(permission::b_channel_join_semi_permanent, channel_id)))
|
||||
RESULT(permission::b_channel_join_semi_permanent);
|
||||
break;
|
||||
case ChannelType::temporary:
|
||||
if(!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_channel_join_temporary, 1, channel, true, permission_cache))
|
||||
RESULT(false);
|
||||
if(!permission::v2::permission_granted(1, this->calculate_permission(permission::b_channel_join_temporary, channel_id)))
|
||||
RESULT(permission::b_channel_join_temporary);
|
||||
break;
|
||||
}
|
||||
if(!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_channel_ignore_join_power, 1, channel, true, permission_cache)) {
|
||||
auto result = this->server->calculatePermissions2(this->getClientDatabaseId(), {permission::i_channel_join_power}, this->getType(), channel->channelId(), false, permission_cache);
|
||||
if(result.empty())
|
||||
RESULT(false);
|
||||
|
||||
if(!channel->permission_granted(permission::i_channel_needed_join_power, result.back().second, false))
|
||||
RESULT(false);
|
||||
if(!channel->permission_granted(permission::i_channel_needed_join_power, this->calculate_permission(permission::i_channel_join_power, channel_id), false)) {
|
||||
if(!permission::v2::permission_granted(1, this->calculate_permission(permission::b_channel_ignore_join_power, channel_id)))
|
||||
RESULT(permission::i_channel_join_power);
|
||||
}
|
||||
|
||||
auto val = this->permissionValue(permission::PERMTEST_ORDERED, permission::b_client_is_sticky, this->currentChannel, permission_cache);
|
||||
if (val != permNotGranted && val > 0) {
|
||||
auto st = this->permissionValue(permission::PERMTEST_ORDERED, permission::b_client_ignore_sticky, this->currentChannel, permission_cache);
|
||||
if (st != 1)
|
||||
RESULT(false);
|
||||
}
|
||||
RESULT(true);
|
||||
if(permission::v2::permission_granted(1, this->calculate_permission(permission::b_client_is_sticky, this->currentChannel ? this->currentChannel->channelId() : 0)))
|
||||
if(!permission::v2::permission_granted(1, this->calculate_permission(permission::b_client_ignore_sticky, channel_id)))
|
||||
RESULT(permission::b_client_is_sticky);
|
||||
RESULT(permission::unknown);
|
||||
}
|
||||
Reference in New Issue
Block a user