A huge permission improvement
This commit is contained in:
parent
49220489ca
commit
6ee207aaad
@ -241,5 +241,8 @@ if(BUILD_TESTS)
|
||||
|
||||
add_executable(LinkedTest test/LinkedTest.cpp ${SOURCE_FILES})
|
||||
target_link_libraries(LinkedTest ${TEST_LIBRARIES})
|
||||
|
||||
add_executable(PermissionTest test/PermissionTest.cpp ${SOURCE_FILES})
|
||||
target_link_libraries(PermissionTest ${TEST_LIBRARIES})
|
||||
endif()
|
||||
endif()
|
||||
|
@ -21,34 +21,9 @@ BasicChannel::BasicChannel(ChannelId parentId, ChannelId channelId) {
|
||||
this->properties()[property::CHANNEL_PID] = parentId;
|
||||
}
|
||||
|
||||
void BasicChannel::setPermissionManager(const std::shared_ptr<ts::permission::PermissionManager>& manager) {
|
||||
auto handler = [&](std::shared_ptr<permission::Permission> perm){
|
||||
if(perm->type->type == permission::i_icon_id)
|
||||
this->properties()[property::CHANNEL_ICON_ID] = (IconId) (perm->hasValue() ? perm->value : 0);
|
||||
else if(perm->type->type == permission::i_client_needed_talk_power) {
|
||||
this->properties()[property::CHANNEL_NEEDED_TALK_POWER] = (perm->hasValue() ? perm->value : 0);
|
||||
}
|
||||
};
|
||||
manager->registerUpdateHandler(handler);
|
||||
//Update channel properties
|
||||
for(const auto& perm : manager->getPermission(permission::i_icon_id, nullptr)) handler(perm);
|
||||
for(const auto& perm : manager->getPermission(permission::i_client_needed_talk_power, nullptr)) handler(perm);
|
||||
|
||||
void BasicChannel::setPermissionManager(const std::shared_ptr<permission::v2::PermissionManager>& manager) {
|
||||
this->_permissions = manager;
|
||||
/*
|
||||
this->_permissions->registerPermission(permission::i_channel_needed_permission_modify_power, 0, nullptr, PERM_FLAG_PUBLIC);
|
||||
this->_permissions->registerPermission(permission::i_channel_needed_join_power, 0, nullptr, PERM_FLAG_PUBLIC);
|
||||
this->_permissions->registerPermission(permission::i_channel_needed_subscribe_power, 0, nullptr, PERM_FLAG_PUBLIC);
|
||||
this->_permissions->registerPermission(permission::i_channel_needed_description_view_power, 0, nullptr, PERM_FLAG_PUBLIC);
|
||||
this->_permissions->registerPermission(permission::i_channel_needed_modify_power, 0, nullptr, PERM_FLAG_PUBLIC);
|
||||
this->_permissions->registerPermission(permission::i_channel_needed_delete_power, 0, nullptr, PERM_FLAG_PUBLIC);
|
||||
this->_permissions->registerPermission(permission::i_ft_needed_file_browse_power, 0, nullptr, PERM_FLAG_PUBLIC);
|
||||
this->_permissions->registerPermission(permission::i_ft_needed_file_upload_power, 0, nullptr, PERM_FLAG_PUBLIC);
|
||||
this->_permissions->registerPermission(permission::i_ft_needed_file_download_power, 0, nullptr, PERM_FLAG_PUBLIC);
|
||||
this->_permissions->registerPermission(permission::i_ft_needed_file_rename_power, 0, nullptr, PERM_FLAG_PUBLIC);
|
||||
this->_permissions->registerPermission(permission::i_ft_needed_directory_create_power, 0, nullptr, PERM_FLAG_PUBLIC);
|
||||
this->_permissions->registerPermission(permission::i_icon_id, 0, nullptr, PERM_FLAG_PUBLIC);
|
||||
*/
|
||||
this->update_properties_from_permissions();
|
||||
}
|
||||
|
||||
void BasicChannel::setProperties(const std::shared_ptr<ts::Properties>& props) {
|
||||
@ -73,6 +48,37 @@ void BasicChannel::setProperties(const std::shared_ptr<ts::Properties>& props) {
|
||||
this->_channel_id = this->channelId();
|
||||
}
|
||||
|
||||
std::vector<property::ChannelProperties> BasicChannel::update_properties_from_permissions() {
|
||||
std::vector<property::ChannelProperties> result;
|
||||
result.reserve(2);
|
||||
|
||||
auto permission_manager = this->permissions(); /* keeps the manager until we've finished our calculations */
|
||||
/* update the icon id */
|
||||
{
|
||||
IconId target_icon_id = 0;
|
||||
auto& permission_icon_flags = permission_manager->permission_flags(permission::i_icon_id);
|
||||
if(permission_icon_flags.value_set)
|
||||
target_icon_id = (IconId) permission_manager->permission_values(permission::i_icon_id).value;
|
||||
if(this->properties()[property::CHANNEL_ICON_ID] != target_icon_id) {
|
||||
this->properties()[property::CHANNEL_ICON_ID] = target_icon_id;
|
||||
result.push_back(property::CHANNEL_ICON_ID);
|
||||
}
|
||||
}
|
||||
/* update the channel talk power */
|
||||
{
|
||||
permission::PermissionValue talk_power = 0;
|
||||
auto& permission_tp_flags = permission_manager->permission_flags(permission::i_client_needed_talk_power);
|
||||
if(permission_tp_flags.value_set)
|
||||
talk_power = (IconId) permission_manager->permission_values(permission::i_client_needed_talk_power).value;
|
||||
if(this->properties()[property::CHANNEL_NEEDED_TALK_POWER] != talk_power) {
|
||||
this->properties()[property::CHANNEL_NEEDED_TALK_POWER] = talk_power;
|
||||
result.push_back(property::CHANNEL_NEEDED_TALK_POWER);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::shared_ptr<BasicChannel> BasicChannel::parent() {
|
||||
auto link_lock = this->_link.lock();
|
||||
if(!link_lock)
|
||||
|
@ -58,8 +58,32 @@ namespace ts {
|
||||
return std::chrono::system_clock::time_point() + std::chrono::milliseconds(this->properties()[property::CHANNEL_CREATED_AT].as<int64_t>());
|
||||
}
|
||||
|
||||
inline std::shared_ptr<permission::PermissionManager> permissions(){ return this->_permissions; }
|
||||
virtual void setPermissionManager(const std::shared_ptr<permission::PermissionManager>&);
|
||||
ts_always_inline bool permission_require_property_update(const permission::PermissionType& permission) {
|
||||
return permission == permission::i_icon_id || permission == permission::i_client_needed_talk_power;
|
||||
}
|
||||
std::vector<property::ChannelProperties> update_properties_from_permissions();
|
||||
|
||||
inline bool permission_granted(const permission::PermissionType& permission, const permission::v2::PermissionFlaggedValue& granted_value, bool require_granted_value) {
|
||||
auto permission_manager = this->permissions(); /* copy the manager */
|
||||
assert(permission_manager);
|
||||
const auto data = permission_manager->permission_value_flagged(permission);
|
||||
if(!data.has_value) {
|
||||
return !require_granted_value || granted_value.has_value;
|
||||
}
|
||||
if(!granted_value.has_value) {
|
||||
return false;
|
||||
}
|
||||
if(data.value == -1) {
|
||||
return granted_value.value == -1;
|
||||
}
|
||||
return granted_value.value >= data.value;
|
||||
}
|
||||
ts_always_inline bool talk_power_granted(const permission::v2::PermissionFlaggedValue& granted_value) {
|
||||
return this->permission_granted(permission::i_client_needed_talk_power, granted_value, false);
|
||||
}
|
||||
|
||||
ts_always_inline std::shared_ptr<permission::v2::PermissionManager> permissions(){ return this->_permissions; }
|
||||
virtual void setPermissionManager(const std::shared_ptr<permission::v2::PermissionManager>&);
|
||||
virtual void setProperties(const std::shared_ptr<Properties>&);
|
||||
protected:
|
||||
public:
|
||||
@ -71,7 +95,7 @@ namespace ts {
|
||||
protected:
|
||||
std::weak_ptr<TreeView::LinkedTreeEntry> _link;
|
||||
std::shared_ptr<Properties> _properties;
|
||||
std::shared_ptr<permission::PermissionManager> _permissions;
|
||||
std::shared_ptr<permission::v2::PermissionManager> _permissions;
|
||||
|
||||
ChannelId _channel_order = 0;
|
||||
ChannelId _channel_id = 0;
|
||||
|
@ -152,4 +152,6 @@ DEFINE_TRANSFORMS(ts::server::ClientType, uint8_t);
|
||||
DEFINE_TRANSFORMS(ts::LicenseType, uint8_t);
|
||||
DEFINE_TRANSFORMS(ts::PluginTargetMode, uint8_t);
|
||||
DEFINE_TRANSFORMS(ts::ViewReasonId, uint8_t);
|
||||
DEFINE_TRANSFORMS(ts::ChatMessageMode, uint8_t);
|
||||
DEFINE_TRANSFORMS(ts::ChatMessageMode, uint8_t);
|
||||
|
||||
#define ts_always_inline inline __attribute__((always_inline))
|
@ -10,7 +10,6 @@ using namespace ts::permission;
|
||||
|
||||
deque<std::shared_ptr<PermissionTypeEntry>> ts::permission::availablePermissions = deque<std::shared_ptr<PermissionTypeEntry>>{
|
||||
make_shared<PermissionTypeEntry>(PermissionType::b_serverinstance_help_view, PermissionGroup::global_info, "b_serverinstance_help_view", "Retrieve information about ServerQuery commands"),
|
||||
//make_shared<PermissionTypeEntry>(PermissionType::b_serverinstance_help_view_teespeack, PermissionGroup::group_7, "b_serverinstance_help_view_teespeack", "Costume teespeck help command idk ist just a test!"),
|
||||
make_shared<PermissionTypeEntry>(PermissionType::b_serverinstance_version_view, PermissionGroup::global_info, "b_serverinstance_version_view", "Retrieve global server version (including platform and build number)"),
|
||||
make_shared<PermissionTypeEntry>(PermissionType::b_serverinstance_info_view, PermissionGroup::global_info, "b_serverinstance_info_view", "Retrieve global server information"),
|
||||
make_shared<PermissionTypeEntry>(PermissionType::b_serverinstance_virtualserver_list, PermissionGroup::global_info, "b_serverinstance_virtualserver_list", "List virtual servers stored in the sql"),
|
||||
@ -18,7 +17,6 @@ deque<std::shared_ptr<PermissionTypeEntry>> ts::permission::availablePermissions
|
||||
//Removed due its useless
|
||||
make_shared<PermissionTypeEntry>(PermissionType::b_serverinstance_permission_list, PermissionGroup::global_info, "b_serverinstance_permission_list", "List permissions available available on the server instance"),
|
||||
make_shared<PermissionTypeEntry>(PermissionType::b_serverinstance_permission_find, PermissionGroup::global_info, "b_serverinstance_permission_find", "Search permission assignments by name or ID"),
|
||||
//make_shared<PermissionTypeEntry>(PermissionType::b_serverinstance_allow_teaspeak_plugin, PermissionGroup::group_7, "b_serverinstance_allow_teespeak_plugin", "Allow a user to use the TeaSpeak plugin extension"),
|
||||
make_shared<PermissionTypeEntry>(PermissionType::b_virtualserver_create, PermissionGroup::global_vsmanage, "b_virtualserver_create", "Create virtual servers"),
|
||||
make_shared<PermissionTypeEntry>(PermissionType::b_virtualserver_delete, PermissionGroup::global_vsmanage, "b_virtualserver_delete", "Delete virtual servers"),
|
||||
make_shared<PermissionTypeEntry>(PermissionType::b_virtualserver_start_any, PermissionGroup::global_vsmanage, "b_virtualserver_start_any", "Start any virtual server in the server instance"),
|
||||
@ -620,20 +618,39 @@ std::deque<PermissionGroup> permission::availableGroups = {
|
||||
|
||||
std::shared_ptr<PermissionTypeEntry> PermissionTypeEntry::unknown = make_shared<PermissionTypeEntry>(PermissionType::unknown, PermissionGroup::global, "unknown", "unknown");
|
||||
|
||||
std::shared_ptr<PermissionTypeEntry> permission::resolvePermissionData(PermissionType type){
|
||||
if((type & PERM_ID_GRANT) > 0) type &= ~PERM_ID_GRANT;
|
||||
for(auto& elm : availablePermissions)
|
||||
if(elm->type == type) return elm;
|
||||
return PermissionTypeEntry::unknown;
|
||||
vector<std::shared_ptr<PermissionTypeEntry>> permission_id_map;
|
||||
void permission::setup_permission_resolve() {
|
||||
permission_id_map.resize(permission::permission_id_max);
|
||||
|
||||
for(auto& permission : availablePermissions) {
|
||||
if(!permission->clientSupported || permission->type < 0 || permission->type > permission::permission_id_max)
|
||||
continue;
|
||||
permission_id_map[permission->type] = permission;
|
||||
}
|
||||
|
||||
/* fix "holes" as well set the permission id 0 (unknown) */
|
||||
for(auto& permission : permission_id_map) {
|
||||
if(permission)
|
||||
continue;
|
||||
permission = PermissionTypeEntry::unknown;
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<PermissionTypeEntry> permission::resolvePermissionData(PermissionType type) {
|
||||
if((type & PERM_ID_GRANT) > 0)
|
||||
type &= ~PERM_ID_GRANT;
|
||||
|
||||
assert(!permission_id_map.empty());
|
||||
if(type < 0 || type >= permission::permission_id_max)
|
||||
return PermissionTypeEntry::unknown;
|
||||
|
||||
return permission_id_map[type];
|
||||
}
|
||||
|
||||
std::shared_ptr<PermissionTypeEntry> permission::resolvePermissionData(const std::string& name) {
|
||||
for(auto& elm : availablePermissions) {
|
||||
if(elm->name == name || elm->grant_name == name) {
|
||||
for(auto& elm : availablePermissions)
|
||||
if(elm->name == name || elm->grant_name == name)
|
||||
return elm;
|
||||
}
|
||||
}
|
||||
debugMessage(LOG_GENERAL, "Could not find permission {}.", name);
|
||||
return PermissionTypeEntry::unknown;
|
||||
}
|
||||
|
||||
@ -1007,4 +1024,445 @@ deque<update::UpdateEntry> update::migrate = {
|
||||
AQB("b_channel_ignore_join_power")
|
||||
AQB("b_virtualserver_select_godmode")
|
||||
AQB("b_client_ban_trigger_list")
|
||||
};
|
||||
};
|
||||
|
||||
v2::PermissionManager::PermissionManager() {
|
||||
memset(this->block_use_count, 0, sizeof(this->block_use_count));
|
||||
memset(this->block_containers, 0, sizeof(this->block_containers));
|
||||
}
|
||||
|
||||
v2::PermissionManager::~PermissionManager() {
|
||||
for(auto& block : this->block_containers)
|
||||
delete block;
|
||||
}
|
||||
|
||||
void v2::PermissionManager::load_permission(const ts::permission::PermissionType &permission, const ts::permission::v2::PermissionValues &values, bool flag_skip, bool flag_negate, bool flag_value, bool flag_grant) {
|
||||
if(permission < 0 || permission >= PermissionType::permission_id_max)
|
||||
return;
|
||||
|
||||
const auto block = this->calculate_block(permission);
|
||||
this->ref_allocate_block(block);
|
||||
|
||||
auto& data = this->block_containers[block]->permissions[this->calculate_block_index(permission)];
|
||||
data.values = values;
|
||||
data.flags.database_reference = true;
|
||||
data.flags.skip = flag_skip;
|
||||
data.flags.negate = flag_negate;
|
||||
data.flags.value_set = flag_value;
|
||||
data.flags.grant_set = flag_grant;
|
||||
this->unref_block(block);
|
||||
}
|
||||
|
||||
void v2::PermissionManager::load_permission(const ts::permission::PermissionType &permission, const ts::permission::v2::PermissionValues &values, ChannelId channel_id, bool flag_skip, bool flag_negate, bool flag_value, bool flag_grant) {
|
||||
if(permission < 0 || permission >= PermissionType::permission_id_max)
|
||||
return;
|
||||
|
||||
unique_lock channel_perm_lock(this->channel_list_lock);
|
||||
ChannelPermissionContainer* permission_container = nullptr;
|
||||
for(auto& entry : this->_channel_permissions)
|
||||
if(entry->permission == permission && entry->channel_id == channel_id) {
|
||||
permission_container = &*entry;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!permission_container) {
|
||||
auto container = make_unique<ChannelPermissionContainer>();
|
||||
container->permission = permission;
|
||||
container->channel_id = channel_id;
|
||||
permission_container = &*container;
|
||||
this->_channel_permissions.push_back(std::move(container));
|
||||
|
||||
/* now set the channel flag for that permission */
|
||||
const auto block = this->calculate_block(permission);
|
||||
this->ref_allocate_block(block);
|
||||
|
||||
auto& data = this->block_containers[block]->permissions[this->calculate_block_index(permission)];
|
||||
data.flags.channel_specific = true;
|
||||
this->unref_block(block);
|
||||
}
|
||||
|
||||
permission_container->values = values;
|
||||
permission_container->flags.database_reference = true;
|
||||
permission_container->flags.skip = flag_skip;
|
||||
permission_container->flags.negate = flag_negate;
|
||||
permission_container->flags.value_set = flag_value;
|
||||
permission_container->flags.grant_set = flag_grant;
|
||||
}
|
||||
|
||||
static constexpr v2::PermissionFlags empty_flags = {false, false, false, false, false, false, 0};
|
||||
const v2::PermissionFlags v2::PermissionManager::permission_flags(const ts::permission::PermissionType &permission) {
|
||||
if(permission < 0 || permission >= PermissionType::permission_id_max)
|
||||
return empty_flags;
|
||||
|
||||
const auto block = this->calculate_block(permission);
|
||||
if(!this->ref_block(block))
|
||||
return empty_flags;
|
||||
|
||||
PermissionFlags result{this->block_containers[block]->permissions[this->calculate_block_index(permission)].flags};
|
||||
this->unref_block(block);
|
||||
return result;
|
||||
}
|
||||
|
||||
const v2::PermissionValues v2::PermissionManager::permission_values(const ts::permission::PermissionType &permission) {
|
||||
if(permission < 0 || permission >= PermissionType::permission_id_max)
|
||||
return v2::empty_permission_values;
|
||||
|
||||
const auto block = this->calculate_block(permission);
|
||||
if(!this->ref_block(block))
|
||||
return v2::empty_permission_values; /* TODO: may consider to throw an exception because the existence should be checked by getting the permission flags */
|
||||
|
||||
v2::PermissionValues data{this->block_containers[block]->permissions[this->calculate_block_index(permission)].values};
|
||||
this->unref_block(block);
|
||||
return data;
|
||||
}
|
||||
|
||||
const v2::PermissionFlaggedValue v2::PermissionManager::permission_value_flagged(const ts::permission::PermissionType &permission) {
|
||||
if(permission < 0 || permission >= PermissionType::permission_id_max)
|
||||
return v2::empty_permission_flagged_value;
|
||||
|
||||
const auto block = this->calculate_block(permission);
|
||||
if(!this->ref_block(block))
|
||||
return v2::empty_permission_flagged_value;
|
||||
|
||||
auto& data = this->block_containers[block]->permissions[this->calculate_block_index(permission)];
|
||||
v2::PermissionFlaggedValue result{data.values.value, data.flags.value_set};
|
||||
this->unref_block(block);
|
||||
return result;
|
||||
}
|
||||
|
||||
const v2::PermissionFlaggedValue v2::PermissionManager::permission_granted_flagged(const ts::permission::PermissionType &permission) {
|
||||
if(permission < 0 || permission >= PermissionType::permission_id_max)
|
||||
return v2::empty_permission_flagged_value;
|
||||
|
||||
const auto block = this->calculate_block(permission);
|
||||
if(!this->ref_block(block))
|
||||
return v2::empty_permission_flagged_value;
|
||||
|
||||
auto& data = this->block_containers[block]->permissions[this->calculate_block_index(permission)];
|
||||
v2::PermissionFlaggedValue result{data.values.grant, data.flags.grant_set};
|
||||
this->unref_block(block);
|
||||
return result;
|
||||
}
|
||||
|
||||
static constexpr v2::PermissionContainer empty_channel_permission = {empty_flags, v2::empty_permission_values};
|
||||
const v2::PermissionContainer v2::PermissionManager::channel_permission(const PermissionType &permission, ts::ChannelId channel_id) {
|
||||
if(permission < 0 || permission >= PermissionType::permission_id_max)
|
||||
return empty_channel_permission;
|
||||
|
||||
shared_lock channel_perm_lock(this->channel_list_lock);
|
||||
for(auto& entry : this->_channel_permissions)
|
||||
if(entry->permission == permission && entry->channel_id == channel_id)
|
||||
return v2::PermissionContainer{entry->flags, entry->values};
|
||||
return empty_channel_permission;
|
||||
}
|
||||
|
||||
void v2::PermissionManager::set_permission(const PermissionType &permission, const v2::PermissionValues &values, const v2::PermissionUpdateType &action_value, const v2::PermissionUpdateType &action_grant, int flag_skip, int flag_negate) {
|
||||
if(permission < 0 || permission >= PermissionType::permission_id_max)
|
||||
return;
|
||||
|
||||
const auto block = this->calculate_block(permission);
|
||||
this->ref_allocate_block(block);
|
||||
|
||||
auto& data = this->block_containers[block]->permissions[this->calculate_block_index(permission)];
|
||||
if(action_value == v2::PermissionUpdateType::set_value) {
|
||||
data.flags.value_set = true;
|
||||
data.flags.flag_value_update = true;
|
||||
data.values.value = values.value;
|
||||
} else if(action_value == v2::PermissionUpdateType::delete_value) {
|
||||
data.flags.value_set = false;
|
||||
data.flags.flag_value_update = true;
|
||||
data.values.grant = permNotGranted; /* required for the database else it does not "deletes" the value */
|
||||
}
|
||||
|
||||
if(action_grant == v2::PermissionUpdateType::set_value) {
|
||||
data.flags.grant_set = true;
|
||||
data.flags.flag_grant_update = true;
|
||||
data.values.grant = values.value;
|
||||
} else if(action_grant == v2::PermissionUpdateType::delete_value) {
|
||||
data.flags.grant_set = false;
|
||||
data.flags.flag_grant_update = true;
|
||||
data.values.grant = permNotGranted; /* required for the database else it does not "deletes" the value */
|
||||
}
|
||||
|
||||
if(flag_skip >= 0)
|
||||
data.flags.skip = flag_skip == 1;
|
||||
|
||||
if(flag_negate >= 0)
|
||||
data.flags.skip = flag_negate == 1;
|
||||
this->unref_block(block);
|
||||
this->trigger_db_update();
|
||||
}
|
||||
|
||||
void v2::PermissionManager::set_channel_permission(const PermissionType &permission, ChannelId channel_id, const v2::PermissionValues &values, const v2::PermissionUpdateType &action_value, const v2::PermissionUpdateType &action_grant, int flag_skip, int flag_negate) {
|
||||
if(permission < 0 || permission >= PermissionType::permission_id_max)
|
||||
return;
|
||||
|
||||
unique_lock channel_perm_lock(this->channel_list_lock);
|
||||
ChannelPermissionContainer* permission_container = nullptr;
|
||||
for(auto& entry : this->_channel_permissions)
|
||||
if(entry->permission == permission && entry->channel_id == channel_id) {
|
||||
permission_container = &*entry;
|
||||
break;
|
||||
}
|
||||
|
||||
/* register a new permission if we have no permission already*/
|
||||
if(!permission_container || !permission_container->flags.permission_set()) { /* if the permission isn't set then we have to register it again */
|
||||
if(action_value != v2::PermissionUpdateType::set_value && action_grant == v2::PermissionUpdateType::set_value) {
|
||||
return; /* we were never willing to set this permission */
|
||||
}
|
||||
|
||||
if(!permission_container) {
|
||||
auto container = make_unique<ChannelPermissionContainer>();
|
||||
container->permission = permission;
|
||||
container->channel_id = channel_id;
|
||||
permission_container = &*container;
|
||||
this->_channel_permissions.push_back(std::move(container));
|
||||
}
|
||||
|
||||
/* now set the channel flag for that permission */
|
||||
const auto block = this->calculate_block(permission);
|
||||
this->ref_allocate_block(block);
|
||||
|
||||
auto& data = this->block_containers[block]->permissions[this->calculate_block_index(permission)];
|
||||
data.flags.channel_specific = true;
|
||||
this->unref_block(block);
|
||||
}
|
||||
|
||||
if(action_value == v2::PermissionUpdateType::set_value) {
|
||||
permission_container->flags.value_set = true;
|
||||
permission_container->flags.flag_value_update = true;
|
||||
permission_container->values.value = values.value;
|
||||
} else if(action_value == v2::PermissionUpdateType::delete_value) {
|
||||
permission_container->flags.value_set = false;
|
||||
permission_container->flags.flag_value_update = true;
|
||||
permission_container->values.grant = permNotGranted; /* required for the database else it does not "deletes" the value */
|
||||
}
|
||||
|
||||
if(action_grant == v2::PermissionUpdateType::set_value) {
|
||||
permission_container->flags.grant_set = true;
|
||||
permission_container->flags.flag_grant_update = true;
|
||||
permission_container->values.grant = values.value;
|
||||
} else if(action_grant == v2::PermissionUpdateType::delete_value) {
|
||||
permission_container->flags.grant_set = false;
|
||||
permission_container->flags.flag_grant_update = true;
|
||||
permission_container->values.grant = permNotGranted; /* required for the database else it does not "deletes" the value */
|
||||
}
|
||||
|
||||
if(flag_skip >= 0)
|
||||
permission_container->flags.skip = flag_skip == 1;
|
||||
|
||||
if(flag_negate >= 0)
|
||||
permission_container->flags.skip = flag_negate == 1;
|
||||
|
||||
if(!permission_container->flags.permission_set()) { /* unregister the permission again because its unset, we delete the channel permission as soon we've flushed the updates */
|
||||
auto other_channel_permission = std::find_if(this->_channel_permissions.begin(), this->_channel_permissions.end(), [&](unique_ptr<ChannelPermissionContainer>& perm) { return perm->permission == permission && perm->flags.permission_set(); });
|
||||
if(other_channel_permission == this->_channel_permissions.end()) { /* no more channel specific permissions c*/
|
||||
const auto block = this->calculate_block(permission);
|
||||
if(this->ref_block(block)) {
|
||||
this->block_containers[block]->permissions[this->calculate_block_index(permission)].flags.channel_specific = false;
|
||||
this->unref_block(block);
|
||||
}
|
||||
}
|
||||
}
|
||||
this->trigger_db_update();
|
||||
}
|
||||
|
||||
const std::vector<std::tuple<PermissionType, const v2::PermissionContainer>> v2::PermissionManager::permissions() {
|
||||
std::unique_lock use_lock(this->block_use_count_lock);
|
||||
decltype(this->block_containers) block_containers; /* save the states/nullptr's */
|
||||
memcpy(block_containers, this->block_containers, sizeof(this->block_containers));
|
||||
size_t block_count = 0;
|
||||
for(size_t index = 0; index < BULK_COUNT; index++) {
|
||||
if(block_containers[index]) {
|
||||
block_count++;
|
||||
this->block_use_count[index]++;
|
||||
}
|
||||
}
|
||||
use_lock.unlock();
|
||||
|
||||
vector<tuple<PermissionType, const v2::PermissionContainer>> result;
|
||||
result.reserve(block_count * PERMISSIONS_BULK_ENTRY_COUNT);
|
||||
|
||||
for(size_t block_index = 0; block_index < BULK_COUNT; block_index++) {
|
||||
auto& block = block_containers[block_index];
|
||||
if(!block)
|
||||
continue;
|
||||
|
||||
for(size_t permission_index = 0; permission_index < PERMISSIONS_BULK_ENTRY_COUNT; permission_index++) {
|
||||
auto& permission = block->permissions[permission_index];
|
||||
if(!permission.flags.permission_set())
|
||||
continue;
|
||||
|
||||
result.emplace_back((PermissionType) (block_index * PERMISSIONS_BULK_ENTRY_COUNT + permission_index), permission);
|
||||
}
|
||||
}
|
||||
result.shrink_to_fit();
|
||||
|
||||
use_lock.lock();
|
||||
for(size_t index = 0; index < BULK_COUNT; index++) {
|
||||
if(block_containers[index])
|
||||
this->block_use_count[index]--;
|
||||
}
|
||||
use_lock.unlock();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const vector<tuple<PermissionType, const v2::PermissionContainer>> v2::PermissionManager::channel_permissions(ts::ChannelId channel_id) {
|
||||
shared_lock channel_perm_lock(this->channel_list_lock);
|
||||
|
||||
vector<tuple<PermissionType, const v2::PermissionContainer>> result;
|
||||
for(auto& entry : this->_channel_permissions)
|
||||
if((channel_id == entry->channel_id) && (entry->flags.value_set || entry->flags.grant_set))
|
||||
result.emplace_back(entry->permission, v2::PermissionContainer{entry->flags, entry->values});
|
||||
return result;
|
||||
}
|
||||
|
||||
const vector<tuple<PermissionType, ChannelId, const v2::PermissionContainer>> v2::PermissionManager::channel_permissions() {
|
||||
shared_lock channel_perm_lock(this->channel_list_lock);
|
||||
|
||||
vector<tuple<PermissionType, ChannelId, const v2::PermissionContainer>> result;
|
||||
for(auto& entry : this->_channel_permissions)
|
||||
if(entry->flags.value_set || entry->flags.grant_set)
|
||||
result.emplace_back(entry->permission, entry->channel_id, v2::PermissionContainer{entry->flags, entry->values});
|
||||
return result;
|
||||
}
|
||||
|
||||
const std::vector<v2::PermissionDBUpdateEntry> v2::PermissionManager::flush_db_updates() {
|
||||
if(!this->requires_db_save)
|
||||
return {};
|
||||
|
||||
this->requires_db_save = false;
|
||||
std::vector<v2::PermissionDBUpdateEntry> result;
|
||||
|
||||
{
|
||||
lock_guard use_lock(this->block_use_count_lock);
|
||||
size_t block_count = 0;
|
||||
for (auto &block_container : block_containers)
|
||||
if (block_container)
|
||||
block_count++;
|
||||
result.reserve(block_count * PERMISSIONS_BULK_ENTRY_COUNT);
|
||||
|
||||
for(size_t block_index = 0; block_index < BULK_COUNT; block_index++) {
|
||||
auto& block = block_containers[block_index];
|
||||
if(!block)
|
||||
continue;
|
||||
|
||||
for(size_t permission_index = 0; permission_index < PERMISSIONS_BULK_ENTRY_COUNT; permission_index++) {
|
||||
auto& permission = block->permissions[permission_index];
|
||||
|
||||
if(!permission.flags.flag_value_update && !permission.flags.flag_grant_update)
|
||||
continue;
|
||||
|
||||
/* we only need an update it the permission has a DB reference or we will set the permission */
|
||||
if(permission.flags.database_reference || permission.flags.permission_set()) {
|
||||
/*
|
||||
PermissionType permission;
|
||||
ChannelId channel_id;
|
||||
|
||||
PermissionValues values;
|
||||
PermissionUpdateType update_value;
|
||||
PermissionUpdateType update_grant;
|
||||
|
||||
bool flag_new: 1;
|
||||
bool flag_skip: 1;
|
||||
bool flag_negate: 1;
|
||||
*/
|
||||
result.push_back(v2::PermissionDBUpdateEntry{
|
||||
(PermissionType) (block_index * PERMISSIONS_BULK_ENTRY_COUNT + permission_index),
|
||||
(ChannelId) 0,
|
||||
|
||||
permission.values,
|
||||
(PermissionUpdateType) (permission.flags.flag_value_update ? (permission.flags.value_set ? PermissionUpdateType::set_value : PermissionUpdateType::delete_value) : PermissionUpdateType::do_nothing),
|
||||
(PermissionUpdateType) (permission.flags.flag_grant_update ? (permission.flags.grant_set ? PermissionUpdateType::set_value : PermissionUpdateType::delete_value) : PermissionUpdateType::do_nothing),
|
||||
|
||||
(bool) permission.flags.database_reference,
|
||||
(bool) !permission.flags.permission_set(), /* db delete */
|
||||
(bool) permission.flags.skip,
|
||||
(bool) permission.flags.negate
|
||||
});
|
||||
permission.flags.database_reference = permission.flags.permission_set();
|
||||
}
|
||||
|
||||
permission.flags.flag_value_update = false;
|
||||
permission.flags.flag_grant_update = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
lock_guard chanel_lock(this->channel_list_lock);
|
||||
for(size_t index = 0; index < this->_channel_permissions.size(); index++) {
|
||||
auto& permission = this->_channel_permissions[index];
|
||||
if(!permission->flags.flag_value_update && !permission->flags.flag_grant_update)
|
||||
continue;
|
||||
|
||||
|
||||
/* we only need an update it the permission has a DB reference or we will set the permission */
|
||||
if(permission->flags.database_reference || permission->flags.permission_set()) {
|
||||
result.push_back(
|
||||
v2::PermissionDBUpdateEntry{
|
||||
permission->permission,
|
||||
permission->channel_id,
|
||||
|
||||
permission->values,
|
||||
permission->flags.flag_value_update ? (permission->flags.value_set ? PermissionUpdateType::set_value : PermissionUpdateType::delete_value) : PermissionUpdateType::do_nothing,
|
||||
permission->flags.flag_grant_update ? (permission->flags.grant_set ? PermissionUpdateType::set_value : PermissionUpdateType::delete_value) : PermissionUpdateType::do_nothing,
|
||||
|
||||
(bool) permission->flags.database_reference,
|
||||
(bool) !permission->flags.permission_set(), /* db delete */
|
||||
(bool) permission->flags.skip,
|
||||
(bool) permission->flags.negate
|
||||
}
|
||||
);
|
||||
permission->flags.database_reference = permission->flags.permission_set();
|
||||
}
|
||||
|
||||
permission->flags.flag_value_update = false;
|
||||
permission->flags.flag_grant_update = false;
|
||||
if(!permission->flags.permission_set()) {
|
||||
this->_channel_permissions.erase(this->_channel_permissions.begin() + index);
|
||||
index--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t v2::PermissionManager::used_memory() {
|
||||
size_t result = sizeof(*this);
|
||||
|
||||
for (auto &block_container : block_containers) {
|
||||
if (block_container)
|
||||
result += sizeof(PermissionContainerBulk<PERMISSIONS_BULK_ENTRY_COUNT>);
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
shared_lock channel_lock(this->channel_list_lock);
|
||||
result += this->_channel_permissions.size() * (sizeof(ChannelPermissionContainer) + sizeof(unique_ptr<ChannelPermissionContainer>));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void v2::PermissionManager::cleanup() {
|
||||
lock_guard use_lock(this->block_use_count_lock);
|
||||
|
||||
for (auto &block_container : block_containers) {
|
||||
if (!block_container) continue;
|
||||
|
||||
bool used = false;
|
||||
for(auto& permission : block_container->permissions) {
|
||||
if(permission.flags.value_set || permission.flags.grant_set || permission.flags.channel_specific) {
|
||||
used = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(used)
|
||||
continue;
|
||||
|
||||
delete block_container;
|
||||
block_container = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <functional>
|
||||
#include <deque>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
#include <cassert>
|
||||
#include <cstring> /* for memset */
|
||||
#include "./misc/spin_lock.h"
|
||||
#include "Definitions.h"
|
||||
#include "Variable.h"
|
||||
|
||||
@ -447,7 +454,9 @@ namespace ts {
|
||||
i_ft_directory_create_power,
|
||||
i_ft_needed_directory_create_power,
|
||||
i_ft_quota_mb_download_per_client,
|
||||
i_ft_quota_mb_upload_per_client
|
||||
i_ft_quota_mb_upload_per_client,
|
||||
|
||||
permission_id_max
|
||||
};
|
||||
inline PermissionType& operator&=(PermissionType& a, int b) { return a = (PermissionType) ((int) a & b); }
|
||||
|
||||
@ -603,6 +612,7 @@ namespace ts {
|
||||
extern std::deque<PermissionType> neededPermissions;
|
||||
extern std::deque<PermissionGroup> availableGroups;
|
||||
|
||||
void setup_permission_resolve();
|
||||
std::shared_ptr<PermissionTypeEntry> resolvePermissionData(PermissionType);
|
||||
std::shared_ptr<PermissionTypeEntry> resolvePermissionData(const std::string&);
|
||||
|
||||
@ -620,7 +630,6 @@ namespace ts {
|
||||
}
|
||||
|
||||
|
||||
|
||||
Permission(Permission &) = delete;
|
||||
Permission(const Permission &) = delete;
|
||||
|
||||
@ -717,6 +726,178 @@ namespace ts {
|
||||
std::deque<std::shared_ptr<Permission>> permissions;
|
||||
std::deque<std::function<void(std::shared_ptr<Permission>)>> updateHandler;
|
||||
};
|
||||
|
||||
namespace v2 {
|
||||
#pragma pack(push, 1)
|
||||
struct PermissionFlags {
|
||||
bool database_reference: 1; /* if set the permission is known within the database, else it has tp be inserted */
|
||||
bool channel_specific: 1; /* set if there are channel specific permissions */
|
||||
|
||||
bool value_set: 1;
|
||||
bool grant_set: 1;
|
||||
|
||||
bool skip: 1;
|
||||
bool negate: 1;
|
||||
|
||||
bool flag_value_update: 1;
|
||||
bool flag_grant_update: 1;
|
||||
|
||||
ts_always_inline bool permission_set() { return this->value_set || this->grant_set; }
|
||||
};
|
||||
static_assert(sizeof(PermissionFlags) == 1);
|
||||
|
||||
struct PermissionValues {
|
||||
PermissionValue value;
|
||||
PermissionValue grant;
|
||||
};
|
||||
static_assert(sizeof(PermissionValues) == 8);
|
||||
static constexpr PermissionValues empty_permission_values{0, 0};
|
||||
|
||||
struct PermissionContainer {
|
||||
PermissionFlags flags;
|
||||
PermissionValues values;
|
||||
};
|
||||
static_assert(sizeof(PermissionContainer) == 9);
|
||||
|
||||
struct ChannelPermissionContainer : public PermissionContainer {
|
||||
PermissionType permission;
|
||||
ChannelId channel_id;
|
||||
};
|
||||
static_assert(sizeof(ChannelPermissionContainer) == 19);
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
#pragma pack(push, 1)
|
||||
template <size_t element_count>
|
||||
struct PermissionContainerBulk {
|
||||
PermissionContainer permissions[element_count];
|
||||
|
||||
PermissionContainerBulk() {
|
||||
memset(this->permissions, 0, sizeof(this->permissions));
|
||||
}
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
enum PermissionUpdateType {
|
||||
do_nothing,
|
||||
set_value,
|
||||
delete_value
|
||||
};
|
||||
|
||||
struct PermissionDBUpdateEntry {
|
||||
PermissionType permission;
|
||||
ChannelId channel_id;
|
||||
|
||||
PermissionValues values;
|
||||
PermissionUpdateType update_value;
|
||||
PermissionUpdateType update_grant;
|
||||
|
||||
bool flag_db: 1; /* only needs an update if set */
|
||||
bool flag_delete: 1;
|
||||
bool flag_skip: 1;
|
||||
bool flag_negate: 1;
|
||||
};
|
||||
|
||||
struct PermissionFlaggedValue {
|
||||
PermissionValue value;
|
||||
bool has_value;
|
||||
};
|
||||
static constexpr PermissionFlaggedValue empty_permission_flagged_value{0, false};
|
||||
|
||||
class PermissionManager {
|
||||
public:
|
||||
static constexpr size_t PERMISSIONS_BULK_BITS = 4; /* 16 permissions per block */
|
||||
static constexpr size_t PERMISSIONS_BULK_ENTRY_COUNT = 1 << PERMISSIONS_BULK_BITS;
|
||||
static constexpr size_t BULK_COUNT = (PermissionType::permission_id_max / (1 << PERMISSIONS_BULK_BITS)) + ((PermissionType::permission_id_max % PERMISSIONS_BULK_ENTRY_COUNT == 0) ? 0 : 1);
|
||||
static_assert(PERMISSIONS_BULK_ENTRY_COUNT * BULK_COUNT >= PermissionType::permission_id_max);
|
||||
|
||||
PermissionManager();
|
||||
virtual ~PermissionManager();
|
||||
|
||||
/* load permissions from the database */
|
||||
void load_permission(const PermissionType&, const PermissionValues& /* values */, bool /* flag negate */, bool /* flag skip */, bool /* value present */,bool /* grant present */);
|
||||
void load_permission(const PermissionType&, const PermissionValues& /* values */, ChannelId /* channel */, bool /* flag negate */, bool /* flag skip */, bool /* value present */,bool /* grant present */);
|
||||
|
||||
/* general getters/setters */
|
||||
const PermissionFlags permission_flags(const PermissionType&); /* we return a "copy" because the actual permission could be deleted while we're analyzing the flags */
|
||||
ts_always_inline const PermissionFlags permission_flags(const std::shared_ptr<PermissionTypeEntry>& permission_info) { return this->permission_flags(permission_info->type); }
|
||||
|
||||
const PermissionValues permission_values(const PermissionType&);
|
||||
ts_always_inline const PermissionValues permission_values(const std::shared_ptr<PermissionTypeEntry>& permission_info) { return this->permission_values(permission_info->type); }
|
||||
|
||||
const PermissionFlaggedValue permission_value_flagged(const PermissionType&);
|
||||
ts_always_inline const PermissionFlaggedValue permission_value_flagged(const std::shared_ptr<PermissionTypeEntry>& permission_info) { return this->permission_value_flagged(permission_info->type); }
|
||||
|
||||
const PermissionFlaggedValue permission_granted_flagged(const PermissionType&);
|
||||
ts_always_inline const PermissionFlaggedValue permission_granted_flagged(const std::shared_ptr<PermissionTypeEntry>& permission_info) { return this->permission_granted_flagged(permission_info->type); }
|
||||
|
||||
/* only worth looking up if channel_specific is set */
|
||||
const PermissionContainer channel_permission(const PermissionType& /* permission */, ChannelId /* channel id */);
|
||||
ts_always_inline const PermissionContainer channel_permission(const std::shared_ptr<PermissionTypeEntry>& permission_info, ChannelId channel_id) { return this->channel_permission(permission_info->type, channel_id); }
|
||||
|
||||
/* modifiers */
|
||||
void set_permission(const PermissionType& /* permission */, const PermissionValues& /* values */, const PermissionUpdateType& /* update value */, const PermissionUpdateType& /* update grant */, int /* flag negate */ = -1, int /* flag skip */ = -1);
|
||||
void set_channel_permission(const PermissionType& /* permission */, ChannelId /* channel id */, const PermissionValues& /* values */, const PermissionUpdateType& /* update value */, const PermissionUpdateType& /* update grant */, int /* flag negate */ = -1, int /* flag skip */ = -1);
|
||||
|
||||
/* bulk info */
|
||||
const std::vector<std::tuple<PermissionType, const PermissionContainer>> permissions();
|
||||
const std::vector<std::tuple<PermissionType, const PermissionContainer>> channel_permissions(ChannelId /* channel id */);
|
||||
const std::vector<std::tuple<PermissionType, ChannelId, const PermissionContainer>> channel_permissions();
|
||||
|
||||
size_t used_memory();
|
||||
void cleanup();
|
||||
|
||||
ts_always_inline bool require_db_updates() { return this->requires_db_save; }
|
||||
const std::vector<PermissionDBUpdateEntry> flush_db_updates();
|
||||
private:
|
||||
static constexpr size_t PERMISSIONS_BULK_BLOCK_MASK = (~(1 << PERMISSIONS_BULK_BITS)) & ((1 << PERMISSIONS_BULK_BITS) - 1);
|
||||
|
||||
bool requires_db_save = false;
|
||||
ts_always_inline void trigger_db_update() { this->requires_db_save = true; } /* todo: pull some kind of trigger? */
|
||||
|
||||
spin_lock block_use_count_lock{};
|
||||
int16_t block_use_count[BULK_COUNT];
|
||||
PermissionContainerBulk<PERMISSIONS_BULK_ENTRY_COUNT>* block_containers[BULK_COUNT];
|
||||
|
||||
std::shared_mutex channel_list_lock{};
|
||||
std::deque<std::unique_ptr<ChannelPermissionContainer>> _channel_permissions{};
|
||||
|
||||
ts_always_inline size_t calculate_block(const PermissionType& permission) {
|
||||
return permission >> PERMISSIONS_BULK_BITS;
|
||||
}
|
||||
|
||||
ts_always_inline size_t calculate_block_index(const PermissionType& permission) {
|
||||
return permission & PERMISSIONS_BULK_BLOCK_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param block
|
||||
* @return true if block exists else false
|
||||
*/
|
||||
ts_always_inline bool ref_block(size_t block) {
|
||||
std::lock_guard use_lock(this->block_use_count_lock);
|
||||
if(!this->block_containers[block])
|
||||
return false;
|
||||
this->block_use_count[block]++;
|
||||
assert(this->block_use_count[block] > 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
ts_always_inline void unref_block(size_t block) {
|
||||
std::lock_guard use_lock(this->block_use_count_lock);
|
||||
this->block_use_count[block]--;
|
||||
assert(this->block_use_count[block] >= 0);
|
||||
}
|
||||
|
||||
ts_always_inline void ref_allocate_block(size_t block) {
|
||||
std::lock_guard use_lock(this->block_use_count_lock);
|
||||
if(!this->block_containers[block])
|
||||
this->block_containers[block] = new PermissionContainerBulk<PERMISSIONS_BULK_ENTRY_COUNT>();
|
||||
this->block_use_count[block]++;
|
||||
assert(this->block_use_count[block] > 0);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,4 +34,6 @@ class spin_lock {
|
||||
always_inline void unlock() {
|
||||
locked.store(false, std::memory_order_release);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
#undef always_inline
|
58
test/PermissionTest.cpp
Normal file
58
test/PermissionTest.cpp
Normal file
@ -0,0 +1,58 @@
|
||||
//
|
||||
// Created by wolverindev on 15.07.19.
|
||||
//
|
||||
|
||||
#include "PermissionManager.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
using namespace ts::permission::v2;
|
||||
using PermissionType = ts::permission::PermissionType;
|
||||
|
||||
void print_permissions(PermissionManager& manager) {
|
||||
{
|
||||
auto permissions = manager.permissions();
|
||||
cout << "Permissions: " << permissions.size() << endl;
|
||||
for(const auto& permission : permissions) {
|
||||
cout << " - " << ts::permission::resolvePermissionData(std::get<0>(permission))->name + ": ";
|
||||
cout << (std::get<1>(permission).flags.value_set ? to_string(std::get<1>(permission).values.value) : "no value") << " negate: " << std::get<1>(permission).flags.negate << " skip: " << std::get<1>(permission).flags.skip << " ";
|
||||
cout << "chan permission: " << std::get<1>(permission).flags.channel_specific << endl;
|
||||
}
|
||||
}
|
||||
cout << "Used memory: " << manager.used_memory() << endl;
|
||||
}
|
||||
|
||||
void print_updates(PermissionManager& manager) {
|
||||
const auto updates = manager.flush_db_updates();
|
||||
cout << "Permission updates: " << updates.size() << endl;
|
||||
for(auto& update : updates) {
|
||||
cout << "Permission: " << ts::permission::resolvePermissionData(update.permission)->name << "; Channel: " << update.channel_id << "; DB Ref: " << update.flag_db << endl;
|
||||
cout << " value: " << (update.update_value == PermissionUpdateType::do_nothing ? "do nothing" : update.update_value == PermissionUpdateType::set_value ? "set value to " + to_string(update.values.value) : "delete") << endl;
|
||||
cout << " grant: " << (update.update_grant == PermissionUpdateType::do_nothing ? "do nothing" : update.update_grant == PermissionUpdateType::set_value ? "set value to " + to_string(update.values.grant) : "delete") << endl;
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
ts::permission::setup_permission_resolve();
|
||||
/*
|
||||
*
|
||||
Structure size of PermissionManager: 176
|
||||
Structure size of PermissionContainerBulk<16>: 192
|
||||
Structure size of PermissionContainer: 12
|
||||
*/
|
||||
cout << "Structure size of PermissionManager: " << sizeof(PermissionManager) << endl;
|
||||
cout << "Structure size of PermissionContainerBulk<16>: " << sizeof(PermissionContainerBulk<16>) << endl;
|
||||
cout << "Structure size of PermissionContainer: " << sizeof(PermissionContainer) << endl;
|
||||
cout << "Permissions/bulk: " << PermissionManager::PERMISSIONS_BULK_ENTRY_COUNT << ". Bulks: " << PermissionManager::BULK_COUNT << " (Max permissions: " << (PermissionManager::PERMISSIONS_BULK_ENTRY_COUNT * PermissionManager::BULK_COUNT) << "; Avl: " << (uint32_t) PermissionType::permission_id_max << ")" << endl;
|
||||
|
||||
PermissionManager manager{};
|
||||
print_permissions(manager);
|
||||
manager.set_permission(PermissionType::b_client_ban_ip, {1, 0}, PermissionUpdateType::set_value, PermissionUpdateType::do_nothing);
|
||||
manager.set_channel_permission(PermissionType::b_client_ban_ip, 2, {1, 0}, PermissionUpdateType::set_value, PermissionUpdateType::do_nothing);
|
||||
manager.set_channel_permission(PermissionType::b_client_ban_ip, 2, {1, 0}, PermissionUpdateType::delete_value, PermissionUpdateType::do_nothing);
|
||||
print_updates(manager);
|
||||
//manager.set_permission(PermissionType::b_client_ban_ip, {1, 0}, PermissionUpdateType::delete_value, PermissionUpdateType::do_nothing);
|
||||
//manager.cleanup();
|
||||
print_permissions(manager);
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user