Using proper permission inheritance
This commit is contained in:
parent
f059e6b3c8
commit
03bad9e6f5
@ -24,35 +24,23 @@ ClientPermissionCalculator::ClientPermissionCalculator(DataClient *client, Chann
|
|||||||
std::shared_ptr<BasicChannel> channel{};
|
std::shared_ptr<BasicChannel> channel{};
|
||||||
try {
|
try {
|
||||||
std::shared_lock channel_lock{server->get_channel_tree_lock()};
|
std::shared_lock channel_lock{server->get_channel_tree_lock()};
|
||||||
channel = server->getChannelTree()->findChannel(channel_id);
|
this->channel_ = server->getChannelTree()->findChannel(channel_id);
|
||||||
} catch (std::system_error& e) {
|
} catch (std::system_error& e) {
|
||||||
if(e.code() != std::errc::resource_deadlock_would_occur) {
|
if(e.code() != std::errc::resource_deadlock_would_occur) {
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* tree already write locked, no need to lock it again */
|
/* tree already write locked, no need to lock it again */
|
||||||
channel = server->getChannelTree()->findChannel(channel_id);
|
this->channel_ = server->getChannelTree()->findChannel(channel_id);
|
||||||
}
|
|
||||||
|
|
||||||
if(channel) {
|
|
||||||
this->channel_permissions = channel->permissions();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->channel_id_ = channel_id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientPermissionCalculator::ClientPermissionCalculator(DataClient *client, const std::shared_ptr<BasicChannel> &channel) {
|
ClientPermissionCalculator::ClientPermissionCalculator(DataClient *client, const std::shared_ptr<BasicChannel> &channel) {
|
||||||
/* Note: Order matters! */
|
/* Note: Order matters! */
|
||||||
this->initialize_client(client);
|
this->initialize_client(client);
|
||||||
this->initialize_default_groups(client->getServer());
|
this->initialize_default_groups(client->getServer());
|
||||||
|
this->channel_ = channel;
|
||||||
if(channel) {
|
|
||||||
this->channel_id_ = channel->channelId();
|
|
||||||
this->channel_permissions = channel->permissions();
|
|
||||||
} else {
|
|
||||||
this->channel_id_ = 0;
|
|
||||||
this->channel_permissions = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientPermissionCalculator::ClientPermissionCalculator(
|
ClientPermissionCalculator::ClientPermissionCalculator(
|
||||||
@ -63,26 +51,21 @@ ClientPermissionCalculator::ClientPermissionCalculator(
|
|||||||
|
|
||||||
this->client_database_id = client_database_id;
|
this->client_database_id = client_database_id;
|
||||||
this->client_type = client_type;
|
this->client_type = client_type;
|
||||||
this->channel_id_ = channel_id;
|
|
||||||
|
|
||||||
if(server) {
|
if(server) {
|
||||||
this->virtual_server_id = server->getServerId();
|
this->virtual_server_id = server->getServerId();
|
||||||
this->group_manager_ = server->group_manager();
|
this->group_manager_ = server->group_manager();
|
||||||
|
|
||||||
std::shared_ptr<BasicChannel> channel{};
|
|
||||||
try {
|
try {
|
||||||
std::shared_lock channel_lock{server->get_channel_tree_lock()};
|
std::shared_lock channel_lock{server->get_channel_tree_lock()};
|
||||||
channel = server->getChannelTree()->findChannel(channel_id);
|
this->channel_ = server->getChannelTree()->findChannel(channel_id);
|
||||||
} catch (std::system_error& e) {
|
} catch (std::system_error& e) {
|
||||||
if(e.code() != std::errc::resource_deadlock_would_occur) {
|
if(e.code() != std::errc::resource_deadlock_would_occur) {
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* tree already write locked, no need to lock it again */
|
/* tree already write locked, no need to lock it again */
|
||||||
channel = server->getChannelTree()->findChannel(channel_id);
|
this->channel_ = server->getChannelTree()->findChannel(channel_id);
|
||||||
}
|
|
||||||
if(channel) {
|
|
||||||
this->channel_permissions = channel->permissions();
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this->virtual_server_id = 0;
|
this->virtual_server_id = 0;
|
||||||
@ -216,8 +199,8 @@ std::vector<std::pair<PermissionType, PermissionFlaggedValue>> ClientPermissionC
|
|||||||
server_group_data_initialized = false; /* reset all group data */
|
server_group_data_initialized = false; /* reset all group data */
|
||||||
auto client_permission_flags = client_permissions->permission_flags(permission);
|
auto client_permission_flags = client_permissions->permission_flags(permission);
|
||||||
/* lets try to resolve the channel specific permission */
|
/* lets try to resolve the channel specific permission */
|
||||||
if(this->channel_id_ > 0 && client_permission_flags.channel_specific) {
|
if(this->channel_ && client_permission_flags.channel_specific) {
|
||||||
auto data = client_permissions->channel_permission(permission, this->channel_id_);
|
auto data = client_permissions->channel_permission(permission, this->channel_->channelId());
|
||||||
if(calculate_granted ? data.flags.grant_set : data.flags.value_set) {
|
if(calculate_granted ? data.flags.grant_set : data.flags.value_set) {
|
||||||
result.push_back({permission, {calculate_granted ? data.values.grant : data.values.value, true}});
|
result.push_back({permission, {calculate_granted ? data.values.grant : data.values.value, true}});
|
||||||
logTrace(this->virtual_server_id, "[Permission] Calculation for client {} of permission {} returned {} (Client channel permission)", this->client_database_id, permission::resolvePermissionData(permission)->name, data.values.value);
|
logTrace(this->virtual_server_id, "[Permission] Calculation for client {} of permission {} returned {} (Client channel permission)", this->client_database_id, permission::resolvePermissionData(permission)->name, data.values.value);
|
||||||
@ -226,7 +209,7 @@ std::vector<std::pair<PermissionType, PermissionFlaggedValue>> ClientPermissionC
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool skip_channel_permissions = this->channel_id_ == 0 || this->has_global_skip_permission();
|
bool skip_channel_permissions = !this->channel_ || this->has_global_skip_permission();
|
||||||
if(!skip_channel_permissions) {
|
if(!skip_channel_permissions) {
|
||||||
/* We dont have a global skip flag. Lets see if the target permission has skip enabled */
|
/* We dont have a global skip flag. Lets see if the target permission has skip enabled */
|
||||||
if(calculate_granted ? client_permission_flags.grant_set : client_permission_flags.value_set) {
|
if(calculate_granted ? client_permission_flags.grant_set : client_permission_flags.value_set) {
|
||||||
@ -262,8 +245,9 @@ std::vector<std::pair<PermissionType, PermissionFlaggedValue>> ClientPermissionC
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* lookup the channel permissions. Whyever? */
|
/* lookup the channel permissions. Whyever? */
|
||||||
if(this->channel_permissions) {
|
if(this->channel_) {
|
||||||
auto data = calculate_granted ? this->channel_permissions->permission_granted_flagged(permission) : this->channel_permissions->permission_value_flagged(permission);
|
auto channel_permissions = this->channel_->permissions();
|
||||||
|
auto data = calculate_granted ? channel_permissions->permission_granted_flagged(permission) : channel_permissions->permission_value_flagged(permission);
|
||||||
if(data.has_value) {
|
if(data.has_value) {
|
||||||
result.push_back({permission, {data.value, true}});
|
result.push_back({permission, {data.value, true}});
|
||||||
logTrace(this->virtual_server_id, "[Permission] Calculation for client {} of permission {} returned {} (Channel permission)", this->client_database_id, permission::resolvePermissionData(permission)->name, data.value);
|
logTrace(this->virtual_server_id, "[Permission] Calculation for client {} of permission {} returned {} (Channel permission)", this->client_database_id, permission::resolvePermissionData(permission)->name, data.value);
|
||||||
@ -341,22 +325,38 @@ const std::shared_ptr<groups::ChannelGroup>& ClientPermissionCalculator::assigne
|
|||||||
}
|
}
|
||||||
|
|
||||||
this->assigned_channel_group_.emplace();
|
this->assigned_channel_group_.emplace();
|
||||||
if(this->channel_id_ == 0) {
|
if(!this->channel_) {
|
||||||
return *this->assigned_channel_group_;
|
return *this->assigned_channel_group_;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto channel_group_assignment = this->group_manager_->assignments().exact_channel_group_of_client(
|
std::shared_ptr<BasicChannel> inherited_channel{this->channel_};
|
||||||
groups::GroupAssignmentCalculateMode::GLOBAL, this->client_database_id, this->channel_id_);
|
auto channel_group_assignment = this->group_manager_->assignments().calculate_channel_group_of_client(
|
||||||
if(!channel_group_assignment.has_value()) {
|
groups::GroupAssignmentCalculateMode::GLOBAL,
|
||||||
return *this->assigned_channel_group_;
|
this->client_database_id,
|
||||||
|
inherited_channel
|
||||||
|
);
|
||||||
|
|
||||||
|
if(channel_group_assignment.has_value()) {
|
||||||
|
assert(inherited_channel);
|
||||||
|
auto channel_group = this->group_manager_->channel_groups()->find_group(groups::GroupCalculateMode::GLOBAL, *channel_group_assignment);
|
||||||
|
if(channel_group) {
|
||||||
|
this->assigned_channel_group_.emplace(std::move(channel_group));
|
||||||
|
logTrace(this->virtual_server_id, "[Permission] Using calculated channel group with id {} (Channel id: {}, Inherited channel id: {}).",
|
||||||
|
*channel_group_assignment, this->channel_->channelId(), inherited_channel->channelId());
|
||||||
|
} else {
|
||||||
|
logTrace(this->virtual_server_id, "[Permission] Missing calculated channel group with id {} (Channel id: {}, Inherited channel id: {}). Using default channel group.",
|
||||||
|
*channel_group_assignment, this->channel_->channelId(), inherited_channel->channelId());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logTrace(this->virtual_server_id, "[Permission] Using default channel group.");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto channel_group = this->group_manager_->channel_groups()->find_group(groups::GroupCalculateMode::GLOBAL, channel_group_assignment->group_id);
|
if(!this->assigned_channel_group_.has_value()) {
|
||||||
if(!channel_group) {
|
assigned_channel_group_.emplace(
|
||||||
channel_group = this->default_channel_group();
|
this->default_channel_group()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
*this->assigned_channel_group_ = channel_group;
|
|
||||||
return *this->assigned_channel_group_;
|
return *this->assigned_channel_group_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,9 +89,9 @@ namespace ts::server {
|
|||||||
ServerId virtual_server_id;
|
ServerId virtual_server_id;
|
||||||
ClientDbId client_database_id;
|
ClientDbId client_database_id;
|
||||||
ClientType client_type;
|
ClientType client_type;
|
||||||
ChannelId channel_id_;
|
std::shared_ptr<BasicChannel> channel_;
|
||||||
|
|
||||||
std::shared_ptr<groups::GroupManager> group_manager_{};
|
std::shared_ptr<groups::GroupManager> group_manager_{};
|
||||||
std::shared_ptr<permission::v2::PermissionManager> channel_permissions{};
|
|
||||||
std::function<std::shared_ptr<groups::ChannelGroup>()> default_channel_group{[]{ return nullptr; }};
|
std::function<std::shared_ptr<groups::ChannelGroup>()> default_channel_group{[]{ return nullptr; }};
|
||||||
std::function<std::shared_ptr<groups::ServerGroup>()> default_server_group{[]{ return nullptr; }};
|
std::function<std::shared_ptr<groups::ServerGroup>()> default_server_group{[]{ return nullptr; }};
|
||||||
|
|
||||||
|
@ -551,7 +551,6 @@ void VirtualServer::client_move(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
TIMING_STEP(timings, "notify view");
|
TIMING_STEP(timings, "notify view");
|
||||||
|
|
||||||
target_client->currentChannel = target_channel;
|
target_client->currentChannel = target_channel;
|
||||||
|
|
||||||
/* third step: update stuff for the client (remember: the client cant execute anything at the moment!) */
|
/* third step: update stuff for the client (remember: the client cant execute anything at the moment!) */
|
||||||
|
@ -1169,32 +1169,36 @@ permission::PermissionType ConnectedClient::calculate_and_get_join_state(const s
|
|||||||
return ventry->join_permission_error;
|
return ventry->join_permission_error;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto channel_id = channel->channelId();
|
ClientPermissionCalculator target_permissions{this, channel};
|
||||||
|
|
||||||
switch(channel->channelType()) {
|
switch(channel->channelType()) {
|
||||||
case ChannelType::permanent:
|
case ChannelType::permanent:
|
||||||
if(!permission::v2::permission_granted(1, this->calculate_permission(permission::b_channel_join_permanent, channel_id))) {
|
if(!target_permissions.permission_granted(permission::b_channel_join_permanent, 1)) {
|
||||||
RESULT(permission::b_channel_join_permanent);
|
RESULT(permission::b_channel_join_permanent);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ChannelType::semipermanent:
|
case ChannelType::semipermanent:
|
||||||
if(!permission::v2::permission_granted(1, this->calculate_permission(permission::b_channel_join_semi_permanent, channel_id))) {
|
if(!target_permissions.permission_granted(permission::b_channel_join_semi_permanent, 1)) {
|
||||||
RESULT(permission::b_channel_join_semi_permanent);
|
RESULT(permission::b_channel_join_semi_permanent);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ChannelType::temporary:
|
case ChannelType::temporary:
|
||||||
if(!permission::v2::permission_granted(1, this->calculate_permission(permission::b_channel_join_temporary, channel_id))) {
|
if(!target_permissions.permission_granted(permission::b_channel_join_temporary, 1)) {
|
||||||
RESULT(permission::b_channel_join_temporary);
|
RESULT(permission::b_channel_join_temporary);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
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))) {
|
auto required_join_power = channel->permissions()->permission_value_flagged(permission::i_channel_needed_join_power);
|
||||||
|
required_join_power.clear_flag_on_zero();
|
||||||
|
if(!target_permissions.permission_granted(permission::i_channel_join_power, required_join_power)) {
|
||||||
|
if(!target_permissions.permission_granted(permission::b_channel_ignore_join_power, 1)) {
|
||||||
RESULT(permission::i_channel_join_power);
|
RESULT(permission::i_channel_join_power);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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_is_sticky, this->getChannelId()))) {
|
||||||
if(!permission::v2::permission_granted(1, this->calculate_permission(permission::b_client_ignore_sticky, channel_id))) {
|
if(!target_permissions.permission_granted(permission::b_client_ignore_sticky, 1)) {
|
||||||
RESULT(permission::b_client_is_sticky);
|
RESULT(permission::b_client_is_sticky);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -526,6 +526,9 @@ command_result ConnectedClient::handleCommandSetClientChannelGroup(Command &cmd)
|
|||||||
for (const auto &targetClient : this->server->findClientsByCldbId(target_cldbid)) {
|
for (const auto &targetClient : this->server->findClientsByCldbId(target_cldbid)) {
|
||||||
connected_client = targetClient;
|
connected_client = targetClient;
|
||||||
|
|
||||||
|
/* Permissions might changed because of group inheritance */
|
||||||
|
targetClient->join_state_id++;
|
||||||
|
|
||||||
bool channel_group_changed, server_group_changed;
|
bool channel_group_changed, server_group_changed;
|
||||||
targetClient->update_displayed_client_groups(server_group_changed, channel_group_changed);
|
targetClient->update_displayed_client_groups(server_group_changed, channel_group_changed);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user