Temporary stashing group changes

This commit is contained in:
WolverinDEV 2021-02-28 19:03:41 +01:00
parent 6f2d8ab6e4
commit 6a7e29b1eb
38 changed files with 1110 additions and 508 deletions

View File

@ -96,6 +96,8 @@ set(SERVER_SOURCE_FILES
src/music/PlayablePlaylist.cpp
src/InstanceHandler.cpp
src/InstanceHandlerSetup.cpp
src/InstanceHandlerPermissions.cpp
src/PermissionCalculator.cpp
src/Configuration.cpp

View File

@ -251,8 +251,7 @@ std::shared_ptr<permission::v2::PermissionManager> DatabaseHelper::find_cached_p
return nullptr;
}
std::shared_ptr<v2::PermissionManager> DatabaseHelper::loadClientPermissionManager(const std::shared_ptr<VirtualServer>& server, ClientDbId cldbid) {
auto server_id = server ? server->getServerId() : 0;
std::shared_ptr<v2::PermissionManager> DatabaseHelper::loadClientPermissionManager(const ServerId& server_id, ClientDbId cldbid) {
#ifndef DISABLE_CACHING
{
std::lock_guard lock{cached_permission_manager_lock};
@ -264,12 +263,12 @@ std::shared_ptr<v2::PermissionManager> DatabaseHelper::loadClientPermissionManag
logTrace(server_id, "[Permission] Loading client permission manager for client {}", cldbid);
auto permission_manager = std::make_shared<v2::PermissionManager>();
bool loaded = false;
if(this->use_startup_cache && server) {
if(this->use_startup_cache && server_id > 0) {
shared_ptr<StartupCacheEntry> entry;
{
threads::MutexLock lock(this->startup_lock);
for(const auto& entries : this->startup_entries) {
if(entries->sid == server->getServerId()) {
if(entries->sid == server_id) {
entry = entries;
break;
}
@ -278,12 +277,11 @@ std::shared_ptr<v2::PermissionManager> DatabaseHelper::loadClientPermissionManag
if(entry) {
for(const auto& perm : entry->permissions) {
if(perm->type == permission::SQL_PERM_USER && perm->id == cldbid) {
auto channel = perm->channelId > 0 ? server->getChannelTree()->findChannel(perm->channelId) : nullptr;
if(channel)
permission_manager->load_permission(perm->permission->type, {perm->value, perm->grant}, channel->channelId(), perm->flag_skip, perm->flag_negate, perm->value != permNotGranted, perm->grant != permNotGranted);
else
if(perm->channelId > 0) {
permission_manager->load_permission(perm->permission->type, {perm->value, perm->grant}, perm->channelId, perm->flag_skip, perm->flag_negate, perm->value != permNotGranted, perm->grant != permNotGranted);
} else {
permission_manager->load_permission(perm->permission->type, {perm->value, perm->grant}, perm->flag_skip, perm->flag_negate, perm->value != permNotGranted, perm->grant != permNotGranted);
}
}
}
loaded = true;
@ -292,7 +290,7 @@ std::shared_ptr<v2::PermissionManager> DatabaseHelper::loadClientPermissionManag
if(!loaded) {
auto command = sql::command(this->sql, "SELECT `permId`, `value`, `channelId`, `grant`, `flag_skip`, `flag_negate` FROM `permissions` WHERE `serverId` = :serverId AND `type` = :type AND `id` = :id",
variable{":serverId", server ? server->getServerId() : 0},
variable{":serverId", server_id},
variable{":type", permission::SQL_PERM_USER},
variable{":id", cldbid});
LOG_SQL_CMD(load_permissions_v2(server_id, permission_manager.get(), command, true, false));

View File

@ -92,7 +92,7 @@ namespace ts::server {
std::deque<std::shared_ptr<ClientDatabaseInfo>> queryDatabaseInfo(const std::shared_ptr<VirtualServer>&, const std::deque<ClientDbId>&);
std::deque<std::shared_ptr<ClientDatabaseInfo>> queryDatabaseInfoByUid(const std::shared_ptr<VirtualServer> &, std::deque<std::string>);
std::shared_ptr<permission::v2::PermissionManager> loadClientPermissionManager(const std::shared_ptr<VirtualServer>&, ClientDbId);
std::shared_ptr<permission::v2::PermissionManager> loadClientPermissionManager(const ServerId&, ClientDbId);
void saveClientPermissions(const std::shared_ptr<VirtualServer>&, ClientDbId , const std::shared_ptr<permission::v2::PermissionManager>& /* permission manager */);
std::shared_ptr<permission::v2::PermissionManager> loadChannelPermissions(const std::shared_ptr<VirtualServer>&, ChannelId);

View File

@ -12,15 +12,6 @@
#include <sql/SqlQuery.h>
namespace ts {
namespace server {
class VirtualServer;
class ConnectedClient;
}
struct CachedClient;
class GroupManager;
class Group;
enum GroupType {
GROUP_TYPE_TEMPLATE,
GROUP_TYPE_NORMAL,
@ -41,198 +32,4 @@ namespace ts {
DEFINE_TRANSFORMS(ts::GroupType, uint8_t);
DEFINE_TRANSFORMS(ts::GroupTarget, uint8_t);
DEFINE_TRANSFORMS(ts::GroupNameMode, uint8_t);
namespace ts {
struct GroupMember {
std::string uid;
uint64_t cldbId;
uint64_t channelId;
std::string displayName;
std::chrono::time_point<std::chrono::system_clock> until;
};
struct GroupAssignment {
GroupAssignment() {}
GroupAssignment(CachedClient *parent, ServerId server, uint64_t channelId, const std::shared_ptr<Group> &group, const std::chrono::time_point<std::chrono::system_clock> &until) : parent(parent), server(server), channelId(channelId), group(group), until(until) {}
CachedClient* parent = nullptr; //Could be null!
ServerId server = 0;
uint64_t channelId = 0;
std::shared_ptr<Group> group;
std::chrono::time_point<std::chrono::system_clock> until;
inline bool isPermanent(){ return std::chrono::time_point_cast<std::chrono::milliseconds>(until).time_since_epoch().count() == 0; }
};
struct CachedClient {
ClientDbId client_database_id;
std::vector<std::shared_ptr<GroupAssignment>> server_groups;
std::map<ts::ChannelId, std::shared_ptr<GroupAssignment>> channel_groups;
size_t use_count = 0;
std::mutex lock; /* never lock this lock before the general client cache! */
};
class Group {
friend class GroupManager;
public:
Group(GroupManager* handle, GroupTarget target, GroupType type, GroupId groupId);
~Group();
std::shared_ptr<permission::v2::PermissionManager> permissions(){ return this->_permissions; }
Properties& properties(){ return *this->_properties; }
GroupNameMode nameMode(){ return (GroupNameMode) (uint8_t) properties()[property::GROUP_NAMEMODE]; }
std::string name(){ return properties()[property::GROUP_NAME]; }
GroupId groupId(){ return properties()[property::GROUP_ID]; }
GroupTarget target() { return _target; }
GroupType type() { return _type; }
void apply_properties_from_permissions();
inline permission::PermissionValue updateType() {
auto permission_manager = this->permissions(); /* copy the manager */
assert(permission_manager);
const auto data = permission_manager->permission_value_flagged(permission::i_group_auto_update_type);
return data.has_value ? data.value : 0;
}
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;
}
inline bool is_permanent() {
auto permission_manager = this->permissions(); /* copy the manager */
assert(permission_manager);
const auto data = permission_manager->permission_value_flagged(permission::b_group_is_permanent);
return data.has_value ? data.value == 1 : false;
}
inline IconId icon_id() {
auto permission_manager = this->permissions(); /* copy the manager */
assert(permission_manager);
const auto data = permission_manager->permission_value_flagged(permission::i_icon_id);
return data.has_value ? data.value : 0;
}
private:
void setPermissionManager(const std::shared_ptr<permission::v2::PermissionManager>& manager);
GroupManager* handle;
std::shared_ptr<permission::v2::PermissionManager> _permissions;
Properties* _properties;
GroupTarget _target;
GroupType _type;
};
class GroupManager {
friend class ServerChannelTree;
friend class Group;
friend class server::VirtualServer;
public:
static int64_t generateGroupId(sql::SqlManager* sql);
GroupManager(const std::shared_ptr<server::VirtualServer> &, sql::SqlManager *, std::shared_ptr<GroupManager> root = nullptr);
~GroupManager();
bool loadGroupFormDatabase(GroupId id = 0);
std::vector<std::shared_ptr<Group>> availableGroups(bool root = true);
std::vector<std::shared_ptr<Group>> availableServerGroups(bool root = true);
std::vector<std::shared_ptr<Group>> availableChannelGroups(bool root = true);
std::vector<std::shared_ptr<GroupAssignment>> getAssignedServerGroups(ClientDbId cldbid);
inline bool hasServerGroupAssigned(uint64_t cldbId, const std::shared_ptr<Group>& group){
for(const auto& assign : this->getAssignedServerGroups(cldbId)) if(assign->group == group) return true;
return false;
}
std::shared_ptr<GroupAssignment> get_group_assignment(const ClientDbId& client_database_id, const std::shared_ptr<Group>& group) {
for(const auto& assign : this->getAssignedServerGroups(client_database_id))
if(assign->group == group) return assign;
return nullptr;
}
std::vector<std::shared_ptr<GroupAssignment>> getServerGroups(ClientDbId cldbid, server::ClientType type);
inline bool hasServerGroup(uint64_t cldbId, server::ClientType type, const std::shared_ptr<Group>& group){
for(const auto& assign : this->getServerGroups(cldbId, type)) if(assign->group == group) return true;
return false;
}
//Gets the channel group (may inherited)
std::shared_ptr<GroupAssignment> getChannelGroup(ClientDbId cldbId, const std::shared_ptr<BasicChannel> &, bool assign_default);
//Gets the channel group within the channel
std::shared_ptr<GroupAssignment> getChannelGroupExact(ClientDbId cldbId, const std::shared_ptr<BasicChannel>&, bool assign_default);
std::vector<std::shared_ptr<GroupAssignment>> defaultServerGroupGroupAssignments(ClientDbId, server::ClientType);
std::shared_ptr<GroupAssignment> defaultChannelGroupAssignment(ClientDbId cldbId, const std::shared_ptr<BasicChannel> &);
void addServerGroup(ClientDbId cldbId, std::shared_ptr<Group>, std::chrono::time_point<std::chrono::system_clock> until = std::chrono::time_point<std::chrono::system_clock>());
void removeServerGroup(ClientDbId cldbId, std::shared_ptr<Group>);
void setChannelGroup(ClientDbId cldbId, std::shared_ptr<Group>, std::shared_ptr<BasicChannel> , std::chrono::time_point<std::chrono::system_clock> until = std::chrono::time_point<std::chrono::system_clock>());
std::shared_ptr<Group> createGroup(GroupTarget target, GroupType type, std::string name);
GroupId copyGroup(std::shared_ptr<Group> group, GroupType type, std::string name, ServerId targetServerId);
bool copyGroupPermissions(const std::shared_ptr<Group>& source, const std::shared_ptr<Group>& target);
bool reloadGroupPermissions(std::shared_ptr<Group>);
bool renameGroup(std::shared_ptr<Group>, std::string);
bool deleteGroup(std::shared_ptr<Group>);
bool deleteAllGroups();
std::deque<GroupMember> listGroupMembers(std::shared_ptr<Group>, bool names = false);
std::vector<std::shared_ptr<GroupAssignment>> listGroupAssignments(ClientDbId client);
void cleanupAssignments(ClientDbId);
std::shared_ptr<Group> findGroup(GroupId);
std::shared_ptr<Group> findGroupLocal(GroupId);
std::vector<std::shared_ptr<Group>> findGroup(GroupTarget target, std::string);
std::shared_ptr<Group> defaultGroup(GroupTarget type, bool enforce_property = false);
std::deque<property::ClientProperties> update_server_group_property(const std::shared_ptr<server::ConnectedClient> &client, bool channel_lock, const std::shared_ptr<BasicChannel>& channel);
void enableCache(const ClientDbId& /* client database id */); /* if this called disableCache(...) MUST be called to decrease the reference count */
void disableCache(const ClientDbId& /* client database id */);
bool isClientCached(const ClientDbId& /* client database id */);
void clearCache();
bool isLocalGroup(std::shared_ptr<Group>);
protected:
void handleChannelDeleted(const ChannelId& /* channel id */);
private:
std::shared_ptr<GroupManager> root = nullptr;
std::weak_ptr<server::VirtualServer> server;
ServerId getServerId();
sql::SqlManager* sql;
std::mutex group_lock{};
std::vector<std::shared_ptr<Group>> groups;
threads::Mutex cacheLock;
std::vector<std::shared_ptr<CachedClient>> cachedClients;
int insertGroupFromDb(int count, char** values, char** column);
inline std::shared_ptr<CachedClient> resolve_cached_client(ClientDbId client_database_id);
};
}
DEFINE_TRANSFORMS(ts::GroupNameMode, uint8_t);

View File

@ -17,6 +17,7 @@
#include <misc/hex.h>
#include <misc/rnd.h>
#include <protocol/buffers.h>
#include "./groups/GroupManager.h"
#ifndef _POSIX_SOURCE
#define _POSIX_SOURCE
@ -32,10 +33,8 @@ using namespace std::chrono;
using namespace ts;
using namespace ts::server;
#define INSTANCE_TICK_NAME "instance"
extern bool mainThreadActive;
InstanceHandler::InstanceHandler(SqlDataManager *sql) : sql(sql) {
InstanceHandler::InstanceHandler(SqlDataManager *sql) : sql(sql), permission_helper_{this} {
serverInstance = this;
this->general_task_executor_ = std::make_shared<task_executor>(ts::config::threads::ticking, "instance tick ");
@ -128,10 +127,49 @@ InstanceHandler::InstanceHandler(SqlDataManager *sql) : sql(sql) {
dynamic_pointer_cast<InternalClient>(this->_musicRoot)->initialize_weak_reference(this->_musicRoot);
{
this->__old__groupManager = std::make_shared<GroupManager>(nullptr, this->getSql());
this->__old__groupManager->loadGroupFormDatabase();
using GroupLoadResult = groups::GroupLoadResult;
if (this->__old__groupManager->availableServerGroups(false).empty()) {
this->group_manager_ = std::make_shared<groups::GroupManager>(this->getSql(), 0, nullptr);
if(!this->group_manager_->initialize(this->group_manager_, error_message)) {
logCritical(LOG_INSTANCE, "Failed to initialize instance group manager: {}", error_message);
mainThreadActive = false;
return;
}
bool initialize_groups{false};
switch(this->group_manager_->server_groups()->load_data(true)) {
case GroupLoadResult::SUCCESS:
break;
case GroupLoadResult::NO_GROUPS:
initialize_groups = true;
break;
case GroupLoadResult::DATABASE_ERROR:
logCritical(LOG_INSTANCE, "Failed to load instance server groups (Database error)");
mainThreadActive = false;
return;
}
switch(this->group_manager_->channel_groups()->load_data(true)) {
case GroupLoadResult::SUCCESS:
break;
case GroupLoadResult::NO_GROUPS:
initialize_groups = true;
break;
case GroupLoadResult::DATABASE_ERROR:
logCritical(LOG_INSTANCE, "Failed to load instance channel groups (Database error)");
mainThreadActive = false;
return;
}
if(!this->group_manager_->assignments().load_data(error_message)) {
logCritical(LOG_INSTANCE, "Failed to load instance group assignments: {}", error_message);
mainThreadActive = false;
return;
}
if (initialize_groups) {
if(!this->setupDefaultGroups()){
logCritical(LOG_INSTANCE, "Could not setup server instance! Stopping...");
mainThreadActive = false;
@ -139,30 +177,7 @@ InstanceHandler::InstanceHandler(SqlDataManager *sql) : sql(sql) {
}
}
debugMessage(LOG_INSTANCE, "Instance admin group id " + to_string(this->properties()[property::SERVERINSTANCE_ADMIN_SERVERQUERY_GROUP].as<GroupId>()));
auto instance_server_admin = this->__old__groupManager->findGroup(this->properties()[property::SERVERINSTANCE_ADMIN_SERVERQUERY_GROUP].as<GroupId>());
if (!instance_server_admin) {
instance_server_admin = this->__old__groupManager->availableServerGroups(false).front();
logCritical(LOG_INSTANCE, "Missing instance server admin group! Using first available (" + (instance_server_admin ? instance_server_admin->name() : "nil") + ")");
}
if(this->__old__groupManager->listGroupAssignments(this->globalServerAdmin->getClientDatabaseId()).empty())
this->__old__groupManager->addServerGroup(this->globalServerAdmin->getClientDatabaseId(), instance_server_admin);
debugMessage(LOG_INSTANCE, "Server guest group id " + to_string(this->properties()[property::SERVERINSTANCE_GUEST_SERVERQUERY_GROUP].as<GroupId>()));
auto instance_server_guest = this->__old__groupManager->findGroup(this->properties()[property::SERVERINSTANCE_GUEST_SERVERQUERY_GROUP].as_save<GroupId>());
if (!instance_server_guest) {
instance_server_guest = this->__old__groupManager->availableServerGroups(false).front();
logCritical(LOG_INSTANCE, "Missing instance server guest group! Using first available (" + (instance_server_guest ? instance_server_guest->name() : "nil") + ")");
}
this->properties()[property::SERVERINSTANCE_GUEST_SERVERQUERY_GROUP] = instance_server_guest->groupId();
debugMessage(LOG_INSTANCE, "Server music group id " + to_string(this->properties()[property::SERVERINSTANCE_TEMPLATE_MUSICDEFAULT_GROUP].as<GroupId>()));
auto instance_server_music = this->__old__groupManager->findGroup(this->properties()[property::SERVERINSTANCE_TEMPLATE_MUSICDEFAULT_GROUP].as_save<GroupId>());
if (!instance_server_music) {
instance_server_music = instance_server_guest;
logCritical(LOG_INSTANCE, "Missing instance server music group! Using serverguest (" + (instance_server_music ? instance_server_music->name() : "nil") + ")");
}
this->properties()[property::SERVERINSTANCE_TEMPLATE_MUSICDEFAULT_GROUP] = instance_server_music->groupId();
this->validate_default_groups();
}
{
@ -214,7 +229,7 @@ InstanceHandler::~InstanceHandler() {
delete this->banMgr;
delete this->dbHelper;
__old__groupManager = nullptr;
group_manager_ = nullptr;
globalServerAdmin = nullptr;
_musicRoot = nullptr;
@ -547,23 +562,14 @@ void InstanceHandler::tickInstance() {
this->properties()[property::SERVERINSTANCE_SPOKEN_TIME_ALIVE] = this->calculateSpokenTime().count();
this->properties()[property::SERVERINSTANCE_SPOKEN_TIME_TOTAL] =
this->properties()[property::SERVERINSTANCE_SPOKEN_TIME_ALIVE].as<uint64_t>() +
this->properties()[property::SERVERINSTANCE_SPOKEN_TIME_DELETED].as<uint64_t>() +
this->properties()[property::SERVERINSTANCE_SPOKEN_TIME_VARIANZ].as<uint64_t>();
this->properties()[property::SERVERINSTANCE_SPOKEN_TIME_ALIVE].as_save<uint64_t>() +
this->properties()[property::SERVERINSTANCE_SPOKEN_TIME_DELETED].as_save<uint64_t>() +
this->properties()[property::SERVERINSTANCE_SPOKEN_TIME_VARIANZ].as_save<uint64_t>();
}
}
void InstanceHandler::save_group_permissions() {
auto groups = this->getOldGroupManager()->availableGroups(false);
for(auto& group : groups) {
auto permissions = group->permissions();
if(permissions->require_db_updates()) {
auto begin = system_clock::now();
serverInstance->databaseHelper()->saveGroupPermissions(0, group->groupId(), 0, permissions);
auto end = system_clock::now();
debugMessage(0, "Saved instance group permissions for group {} ({}) in {}ms", group->groupId(), group->name(), duration_cast<milliseconds>(end - begin).count());
}
}
this->group_manager()->save_permissions();
}
void InstanceHandler::save_channel_permissions() {
@ -884,35 +890,58 @@ void InstanceHandler::loadWebCertificate() {
this->web_cert_revision = revision;
}
bool InstanceHandler::validate_default_groups() {
using groups::GroupCalculateMode;
using groups::GroupAssignmentCalculateMode;
permission::v2::PermissionFlaggedValue InstanceHandler::calculate_permission(permission::PermissionType permission,
ClientDbId cldbid, ClientType type, ChannelId channel, bool granted, std::shared_ptr<CalculateCache> cache) {
auto result = this->calculate_permissions({permission}, cldbid, type, channel, granted, cache);
if(result.empty()) return {0, false};
return result.front().second;
}
{
auto property = this->properties()[property::SERVERINSTANCE_ADMIN_SERVERQUERY_GROUP];
auto group_id = property.as_save<GroupId>();
debugMessage(LOG_INSTANCE, "Instance admin query group id {}", group_id);
std::vector<std::pair<permission::PermissionType, permission::v2::PermissionFlaggedValue> > InstanceHandler::calculate_permissions(
const std::deque<permission::PermissionType> &permissions, ClientDbId cldbid, ClientType type, ChannelId channel, bool granted, std::shared_ptr<CalculateCache> cache) {
std::vector<std::pair<permission::PermissionType, permission::v2::PermissionFlaggedValue>> result{};
auto group_instance = this->group_manager_->server_groups()->find_group(GroupCalculateMode::GLOBAL, group_id);
if(!group_instance) {
auto available_groups = this->group_manager_->server_groups()->available_groups(GroupCalculateMode::GLOBAL);
if(available_groups.empty()) {
logCritical(LOG_INSTANCE, "Missing instance server groups.");
return false;
}
//TODO: Negate?
//TODO: May move this part to the instance?
auto server_groups = this->getOldGroupManager()->getServerGroups(cldbid, type);
for(const auto& permission : permissions) {
permission::v2::PermissionFlaggedValue value{0, false};
for(const auto &gr : server_groups){
auto group_permissions = gr->group->permissions();
auto flagged_permissions = granted ? group_permissions->permission_granted_flagged(permission) : group_permissions->permission_value_flagged(permission);
if(flagged_permissions.has_value)
if(!value.has_value || flagged_permissions.value > value.value || flagged_permissions.value == -1)
value = flagged_permissions;
group_instance = available_groups.front();
logCritical(LOG_INSTANCE, "Missing instance server admin query group. Using first available ({})", group_instance->group_id());
}
result.emplace_back(permission, value);
property.update_value(group_instance->group_id());
{
auto& assignments = this->group_manager_->assignments();
auto client_assignments = assignments.server_groups_of_client(GroupAssignmentCalculateMode::GLOBAL, this->globalServerAdmin->getClientDatabaseId());
if(client_assignments.empty()) {
assignments.add_server_group(this->globalServerAdmin->getClientDatabaseId(), group_instance->group_id());
}
}
}
return result;
}
{
auto property = this->properties()[property::SERVERINSTANCE_GUEST_SERVERQUERY_GROUP];
auto group_id = property.as_save<GroupId>();
debugMessage(LOG_INSTANCE, "Instance guest query group id {}", group_id);
auto group_instance = this->group_manager_->server_groups()->find_group(GroupCalculateMode::GLOBAL, group_id);
if(!group_instance) {
auto available_groups = this->group_manager_->server_groups()->available_groups(GroupCalculateMode::GLOBAL);
if(available_groups.empty()) {
logCritical(LOG_INSTANCE, "Missing instance server groups.");
return false;
}
group_instance = available_groups.front();
logCritical(LOG_INSTANCE, "Missing instance server guest query group. Using first available ({})", group_instance->group_id());
}
property.update_value(group_instance->group_id());
}
return true;
}
InstancePermissionHelper::InstancePermissionHelper(InstanceHandler *instance) : instance{instance} {}

View File

@ -32,7 +32,38 @@ namespace ts {
class ActionLogger;
}
namespace groups {
class GroupManager;
}
class ServerCommandExecutor;
class InstanceHandler;
struct InstancePermissionHelper {
public:
explicit InstancePermissionHelper(InstanceHandler*);
permission::v2::PermissionFlaggedValue calculate_permission(
permission::PermissionType,
ClientDbId,
ClientType type,
ChannelId channel,
bool granted = false,
std::shared_ptr<CalculateCache> cache = nullptr
) const;
std::vector<std::pair<permission::PermissionType, permission::v2::PermissionFlaggedValue>> calculate_permissions(
const std::deque<permission::PermissionType>&,
ClientDbId,
ClientType type,
ChannelId channel,
bool granted = false,
std::shared_ptr<CalculateCache> cache = nullptr
) const;
private:
InstanceHandler* instance;
};
class InstanceHandler {
public:
@ -47,7 +78,7 @@ namespace ts {
}
std::shared_ptr<ts::server::InternalClient> getInitialServerAdmin(){ return globalServerAdmin; }
std::shared_ptr<ts::GroupManager> getOldGroupManager(){ return __old__groupManager; }
const auto& group_manager(){ return this->group_manager_; }
std::shared_ptr<ts::ServerChannelTree> getChannelTree() { return this->default_tree; }
std::shared_mutex& getChannelTreeLock() { return this->default_tree_lock; }
@ -87,24 +118,7 @@ namespace ts {
std::shared_ptr<ts::event::EventExecutor> getConversationIo() { return this->conversation_io; }
[[nodiscard]] inline const auto& server_command_executor() { return this->server_command_executor_; }
permission::v2::PermissionFlaggedValue calculate_permission(
permission::PermissionType,
ClientDbId,
ClientType type,
ChannelId channel,
bool granted = false,
std::shared_ptr<CalculateCache> cache = nullptr
);
std::vector<std::pair<permission::PermissionType, permission::v2::PermissionFlaggedValue>> calculate_permissions(
const std::deque<permission::PermissionType>&,
ClientDbId,
ClientType type,
ChannelId channel,
bool granted = false,
std::shared_ptr<CalculateCache> cache = nullptr
);
[[nodiscard]] inline const auto& permission_helper() { return this->permission_helper_; }
[[nodiscard]] inline std::shared_ptr<license::LicenseService> license_service() { return this->license_service_; }
private:
@ -141,9 +155,12 @@ namespace ts {
std::shared_ptr<weblist::WebListManager> web_list = nullptr;
std::shared_ptr<ts::Properties> default_server_properties = nullptr;
std::shared_ptr<ts::ServerChannelTree> default_tree = nullptr;
std::shared_mutex default_tree_lock;
std::shared_ptr<ts::GroupManager> __old__groupManager = nullptr;
std::shared_ptr<ts::ServerChannelTree> default_tree = nullptr;
InstancePermissionHelper permission_helper_;
std::shared_ptr<groups::GroupManager> group_manager_{nullptr};
std::shared_ptr<ts::server::InternalClient> globalServerAdmin = nullptr;
std::shared_ptr<ConnectedClient> _musicRoot = nullptr;
@ -167,6 +184,7 @@ namespace ts {
void save_channel_permissions();
void loadWebCertificate();
bool validate_default_groups();
};
}
}

View File

@ -0,0 +1,76 @@
//
// Created by WolverinDEV on 26/02/2021.
//
#include "./InstanceHandler.h"
#include "./groups/GroupManager.h"
using namespace ts;
using namespace ts::server;
permission::v2::PermissionFlaggedValue InstancePermissionHelper::calculate_permission(
permission::PermissionType permission,
ClientDbId cldbid,
ClientType type,
ChannelId channel,
bool granted,
std::shared_ptr<CalculateCache> cache
) const {
auto result = this->calculate_permissions({permission}, cldbid, type, channel, granted, cache);
if(result.empty()) return {0, false};
return result.front().second;
}
std::vector<std::pair<permission::PermissionType, permission::v2::PermissionFlaggedValue> > InstancePermissionHelper::calculate_permissions(
const std::deque<permission::PermissionType> &permissions,
ClientDbId cldbid,
ClientType /* type */,
ChannelId /* channel */,
bool granted,
std::shared_ptr<CalculateCache> /* cache */
) const {
std::vector<std::pair<permission::PermissionType, permission::v2::PermissionFlaggedValue>> result{};
/* TODO: Use same algorithm as on normal servers */
std::vector<std::shared_ptr<groups::ServerGroup>> assigned_groups{};
{
using groups::GroupAssignmentCalculateMode;
using groups::GroupCalculateMode;
auto group_manager = this->instance->group_manager();
auto& assignment_manager = group_manager->assignments();
auto assignments = assignment_manager.server_groups_of_client(GroupAssignmentCalculateMode::GLOBAL, cldbid);
if(assignments.empty()) {
assignments.push_back(this->instance->properties()[property::SERVERINSTANCE_GUEST_SERVERQUERY_GROUP].as_save<GroupId>());
}
assigned_groups.reserve(assignments.size());
for(const auto& group_id : assignments) {
auto group = group_manager->server_groups()->find_group(GroupCalculateMode::GLOBAL, group_id);
if(!group) {
continue;
}
assigned_groups.push_back(std::move(group));
}
}
for(const auto& permission : permissions) {
permission::v2::PermissionFlaggedValue value{0, false};
for(const auto &gr : assigned_groups){
auto group_permissions = gr->permissions();
auto flagged_permissions = granted ? group_permissions->permission_granted_flagged(permission) : group_permissions->permission_value_flagged(permission);
if(flagged_permissions.has_value) {
if(!value.has_value || flagged_permissions.value > value.value || flagged_permissions.value == -1) {
value = flagged_permissions;
}
}
}
result.emplace_back(permission, value);
}
return result;
}

View File

@ -123,7 +123,7 @@ bool InstanceHandler::setupDefaultGroups() {
for(const auto& info : groups) {
debugMessage(LOG_INSTANCE, "Creating default group {} with type {}", info->name, to_string(info->target));
//Query groups
auto group = this->__old__groupManager->createGroup(
auto group = this->group_manager_->createGroup(
info->target != 2 ? GroupTarget::GROUPTARGET_SERVER : GroupTarget::GROUPTARGET_CHANNEL,
info->target == 0 ? GroupType::GROUP_TYPE_QUERY : GroupType::GROUP_TYPE_TEMPLATE,
info->name

View File

@ -0,0 +1,343 @@
//
// Created by WolverinDEV on 27/02/2021.
//
#include "./PermissionCalculator.h"
#include "./InstanceHandler.h"
#include "./groups/Group.h"
#include "./client/DataClient.h"
#include <PermissionManager.h>
#include <log/LogUtils.h>
#include <src/groups/GroupManager.h>
using namespace ts::server;
using ts::permission::PermissionType;
using ts::permission::v2::PermissionFlaggedValue;
ClientPermissionCalculator::ClientPermissionCalculator(DataClient *client, ChannelId channel_id) {
this->initialize_client(client);
auto server = client->getServer();
if(server && channel_id > 0) {
std::shared_lock channel_lock{server->get_channel_tree_lock()};
auto channel = server->getChannelTree()->findChannel(channel_id);
channel_lock.unlock();
if(channel) {
this->channel_permissions = channel->permissions();
}
}
this->channel_id_ = channel_id;
}
ClientPermissionCalculator::ClientPermissionCalculator(DataClient *client, const std::shared_ptr<BasicChannel> &channel) {
this->initialize_client(client);
if(channel) {
this->channel_id_ = channel->channelId();
this->channel_permissions = channel->permissions();
} else {
this->channel_id_ = 0;
this->channel_permissions = nullptr;
}
}
ClientPermissionCalculator::ClientPermissionCalculator(
const std::shared_ptr<VirtualServer> &server,
ClientDbId client_database_id,
ClientType client_type,
ChannelId channel_id) {
this->client_database_id = client_database_id;
this->client_type = client_type;
this->channel_id_ = channel_id;
if(server) {
this->virtual_server_id = server->getServerId();
this->group_manager_ = server->group_manager();
this->default_channel_group = [server]{ return server->default_channel_group(); };
std::shared_lock channel_lock{server->get_channel_tree_lock()};
auto channel = server->getChannelTree()->findChannel(channel_id);
channel_lock.unlock();
if(channel) {
this->channel_permissions = channel->permissions();
}
} else {
this->virtual_server_id = 0;
this->group_manager_ = serverInstance->group_manager();
}
}
void ClientPermissionCalculator::initialize_client(DataClient* client) {
this->virtual_server_id = client->getServerId();
this->client_database_id = client->getClientDatabaseId();
this->client_type = client->getType();
this->client_permissions = client->permissions();
auto server = client->getServer();
if(server) {
this->group_manager_ = server->group_manager();
this->default_channel_group = [server]{ return server->default_channel_group(); };
} else {
this->group_manager_ = serverInstance->group_manager();
}
}
std::vector<std::pair<PermissionType, PermissionFlaggedValue>> ClientPermissionCalculator::calculate_permissions(
const std::deque<permission::PermissionType> &permissions,
bool calculate_granted
) {
if(permissions.empty()) {
return {};
}
std::vector<std::pair<PermissionType, PermissionFlaggedValue>> result;
result.reserve(permissions.size());
if(!this->client_permissions) {
this->client_permissions = serverInstance->databaseHelper()->loadClientPermissionManager(this->virtual_server_id, this->client_database_id);
if(!this->client_permissions) {
logCritical(this->virtual_server_id, "Failed to load client permissions for client {}", this->client_database_id);
for(size_t index{0}; index < permissions.size(); index++) {
result.emplace_back(permissions[index], PermissionFlaggedValue{ 0, false });
}
return result;
}
}
bool have_skip_permission{false};
int skip_permission_type{-1}; /* -1 := unset | 0 := skip, not explicit | 1 := skip, explicit */
/*
* server_group_data[0] := Server group id
* server_group_data[1] := Skip flag
* server_group_data[2] := Negate flag
* server_group_data[3] := Permission value
*/
typedef std::tuple<GroupId, bool, bool, permission::PermissionValue> GroupData;
bool server_group_data_initialized = false;
std::vector<GroupData> server_group_data;
GroupData* active_server_group;
/* function to calculate skip permission */
auto calculate_skip = [&]{
skip_permission_type = 0;
/* test for skip permission within the client permission manager */
{
auto skip_value = this->client_permissions->permission_value_flagged(permission::b_client_skip_channelgroup_permissions);
if(skip_value.has_value) {
have_skip_permission = skip_value.value == 1;
skip_permission_type = 1;
logTrace(this->virtual_server_id, "[Permission] Found skip permission in client permissions. Value: {}", have_skip_permission);
}
}
/* test for skip permission within all server groups */
if(skip_permission_type != 1) {
for(const auto& assignment : this->assigned_server_groups()) {
auto group_permissions = assignment->permissions();
auto flagged_value = group_permissions->permission_value_flagged(permission::b_client_skip_channelgroup_permissions);
if(flagged_value.has_value) {
have_skip_permission |= flagged_value.value == 1;
if(have_skip_permission) {
logTrace(this->virtual_server_id, "[Permission] Found skip permission in client server group. Group: {} ({}), Value: {}", assignment->group_id(), assignment->display_name(), have_skip_permission);
break;
}
}
}
}
};
auto initialize_group_data = [&](const permission::PermissionType& permission_type) {
server_group_data_initialized = true;
active_server_group = nullptr;
auto assigned_groups = this->assigned_server_groups();
server_group_data.resize(assigned_groups.size());
auto it = server_group_data.begin();
for(auto& group : assigned_groups) {
auto group_permissions = group->permissions();
auto permission_flags = group_permissions->permission_flags(permission_type);
auto flag_set = calculate_granted ? permission_flags.grant_set : permission_flags.value_set;
if(!flag_set) {
continue;
}
//TODO: Test if there is may a group channel permissions
auto value = group_permissions->permission_values(permission_type);
*it = std::make_tuple(group->group_id(), (bool) permission_flags.skip, (bool) permission_flags.negate, calculate_granted ? value.grant : value.value);
it++;
}
if(it == server_group_data.begin()) {
return; /* no server group has that permission */
}
server_group_data.erase(it, server_group_data.end()); /* remove unneeded */
auto found_negate = false;
for(auto& group : server_group_data) {
if(std::get<2>(group)) {
found_negate = true;
break;
}
}
if(found_negate) {
server_group_data.erase(remove_if(server_group_data.begin(), server_group_data.end(), [](auto data) { return !std::get<2>(data); }), server_group_data.end());
logTrace(this->virtual_server_id, "[Permission] Found negate flag within server groups. Groups left: {}", server_group_data.size());
if(server_group_data.empty()) {
logTrace(this->virtual_server_id, "[Permission] After non negated groups have been kicked out the negated groups are empty! This should not happen! Permission: {}, Client ID: {}", permission_type, this->client_database_id);
}
permission::PermissionValue current_lowest = 0;
for(auto& group : server_group_data) {
if(!active_server_group || (std::get<3>(group) < current_lowest && std::get<3>(group) != -1)) {
current_lowest = std::get<3>(group);
active_server_group = &group;
}
}
} else {
permission::PermissionValue current_highest = 0;
for(auto& group : server_group_data) {
if(!active_server_group || (std::get<3>(group) > current_highest || std::get<3>(group) == -1)) {
current_highest = std::get<3>(group);
active_server_group = &group;
}
}
}
};
for(const auto& permission : permissions) {
server_group_data_initialized = false; /* reset all group data */
auto client_permission_flags = this->client_permissions->permission_flags(permission);
/* lets try to resolve the channel specific permission */
if(this->channel_id_ > 0 && client_permission_flags.channel_specific) {
auto data = this->client_permissions->channel_permission(permission, this->channel_id_);
if(calculate_granted ? data.flags.grant_set : data.flags.value_set) {
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);
continue;
}
}
bool skip_channel_permissions = this->channel_id_ == 0;
if(!skip_channel_permissions) {
/* look if somewhere is the skip permission flag set */
if(skip_permission_type == -1) {/* initialize skip flag */
calculate_skip();
}
skip_channel_permissions = have_skip_permission;
}
if(!skip_channel_permissions) {
/* okey we've no global skip. Then now lookup the groups and the client permissions */
if(calculate_granted ? client_permission_flags.grant_set : client_permission_flags.value_set) {
/* okey the client has the permission, this counts */
skip_channel_permissions = client_permission_flags.skip;
} else {
if(!server_group_data_initialized) {
initialize_group_data(permission);
}
if(active_server_group) {
skip_channel_permissions = std::get<1>(*active_server_group);
}
}
}
if(!skip_channel_permissions) {
/* lookup the channel group */
{
auto channel_assignment = this->assigned_channel_group();
if(channel_assignment) {
auto group_permissions = channel_assignment->permissions();
auto permission_flags = group_permissions->permission_flags(permission);
auto flag_set = calculate_granted ? permission_flags.grant_set : permission_flags.value_set;
if(flag_set) {
auto value = group_permissions->permission_values(permission);
result.push_back({permission, {calculate_granted ? value.grant : value.value, true}});
logTrace(this->virtual_server_id, "[Permission] Calculation for client {} of permission {} returned {} (Channel group permission)", this->client_database_id, permission::resolvePermissionData(permission)->name, calculate_granted ? value.grant : value.value);
continue;
}
}
}
/* lookup the channel permissions. Whyever? */
if(this->channel_permissions) {
auto data = calculate_granted ? this->channel_permissions->permission_granted_flagged(permission) : this->channel_permissions->permission_value_flagged(permission);
if(data.has_value) {
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);
continue;
}
}
}
if(calculate_granted ? client_permission_flags.grant_set : client_permission_flags.value_set) {
auto client_value = this->client_permissions->permission_values(permission);
result.push_back({permission, {calculate_granted ? client_value.grant : client_value.value, true}});
logTrace(this->virtual_server_id, "[Permission] Calculation for client {} of permission {} returned {} (Client permission)", this->client_database_id, permission::resolvePermissionData(permission)->name, client_value.value);
continue;
}
if(!server_group_data_initialized) {
initialize_group_data(permission);
}
if(active_server_group) {
result.push_back({permission, {get<3>(*active_server_group), true}});
logTrace(this->virtual_server_id, "[Permission] Calculation for client {} of permission {} returned {} (Server group permission of group {})", this->client_database_id, permission::resolvePermissionData(permission)->name, get<3>(*active_server_group), get<0>(*active_server_group));
continue;
}
logTrace(this->virtual_server_id, "[Permission] Calculation for client {} of permission {} returned in no permission.", this->client_database_id, permission::resolvePermissionData(permission)->name);
result.push_back({permission, {permNotGranted, false}});
}
return result;
}
const std::vector<std::shared_ptr<groups::ServerGroup>>& ClientPermissionCalculator::assigned_server_groups() {
if(this->assigned_server_groups_.has_value()) {
return *this->assigned_server_groups_;
}
auto assignments = this->group_manager_->assignments().server_groups_of_client(groups::GroupAssignmentCalculateMode::GLOBAL, this->client_database_id);
this->assigned_server_groups_.emplace();
this->assigned_server_groups_->reserve(assignments.size());
for(const auto& group_id : assignments) {
auto group = this->group_manager_->server_groups()->find_group(groups::GroupCalculateMode::GLOBAL, group_id);
if(group) {
this->assigned_server_groups_->push_back(group);
}
}
return *this->assigned_server_groups_;
}
const std::shared_ptr<groups::ChannelGroup>& ClientPermissionCalculator::assigned_channel_group() {
if(this->assigned_channel_group_.has_value()) {
return *this->assigned_channel_group_;
}
this->assigned_channel_group_.emplace();
if(this->channel_id_ == 0) {
return *this->assigned_channel_group_;
}
auto channel_group_assignment = this->group_manager_->assignments().channel_group_of_client(groups::GroupAssignmentCalculateMode::GLOBAL, this->client_database_id, this->channel_id_);
if(!channel_group_assignment.has_value()) {
return *this->assigned_channel_group_;
}
auto channel_group = this->group_manager_->channel_groups()->find_group(groups::GroupCalculateMode::GLOBAL, channel_group_assignment->group_id);
if(!channel_group) {
channel_group = this->default_channel_group();
}
*this->assigned_channel_group_ = channel_group;
return *this->assigned_channel_group_;
}

View File

@ -0,0 +1,83 @@
#pragma once
#include <Definitions.h>
#include <PermissionManager.h>
#include <vector>
#include <memory>
namespace ts {
class BasicChannel;
}
namespace ts::server {
class DataClient;
class VirtualServer;
namespace groups {
class ChannelGroup;
class ServerGroup;
class GroupManager;
}
/**
* Helper for calculating the client permissions for a certain channel.
* Note: All functions are not thread save!
*/
class ClientPermissionCalculator {
public:
explicit ClientPermissionCalculator(DataClient* /* client */, const std::shared_ptr<BasicChannel>& /* target channel */);
explicit ClientPermissionCalculator(DataClient* /* client */, ChannelId /* target channel id */);
explicit ClientPermissionCalculator(
const std::shared_ptr<VirtualServer>& /* server */,
ClientDbId /* client database id */,
ClientType /* client type */,
ChannelId /* target channel id */
);
/**
* Calculate the given permissions.
* This method can be called from everywhere without any locking needed.
* @param granted
* @return
*/
permission::v2::PermissionFlaggedValue calculate_permission(
permission::PermissionType,
bool granted = false
);
/**
* Calculate the given permissions.
* This method can be called from everywhere without any locking needed.
* @param channel
* @param calculate_granted
* @return
*/
std::vector<std::pair<permission::PermissionType, permission::v2::PermissionFlaggedValue>> calculate_permissions(
const std::deque<permission::PermissionType>&,
bool calculate_granted = false
);
private:
/* given fields */
ServerId virtual_server_id;
ClientDbId client_database_id;
ClientType client_type;
ChannelId channel_id_;
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; }};
/* fields which will be set when calculating permissions */
std::shared_ptr<permission::v2::PermissionManager> client_permissions{};
bool global_skip{false};
bool global_skip_set{false};
std::optional<std::shared_ptr<groups::ChannelGroup>> assigned_channel_group_{};
std::optional<std::vector<std::shared_ptr<groups::ServerGroup>>> assigned_server_groups_{};
void initialize_client(DataClient* /* client */);
[[nodiscard]] const std::vector<std::shared_ptr<groups::ServerGroup>>& assigned_server_groups();
[[nodiscard]] const std::shared_ptr<groups::ChannelGroup>& assigned_channel_group();
};
}

View File

@ -978,7 +978,7 @@ bool VirtualServerManager::createServerSnapshot(Command &cmd, shared_ptr<Virtual
//List groups
{
cmd[index]["server_groups"] = "";
for(const auto& group : server->getGroupManager()->availableServerGroups(false)) {
for(const auto& group : server->group_manager()->availableServerGroups(false)) {
cmd[index]["id"] = group->groupId();
cmd[index]["name"] = group->name();
if(!writePermissions(group->permissions(), cmd, index, version, permission::teamspeak::SERVER, error)) break;
@ -1000,7 +1000,7 @@ bool VirtualServerManager::createServerSnapshot(Command &cmd, shared_ptr<Virtual
//List groups
{
cmd[index]["channel_groups"] = "";
for(const auto& group : server->getGroupManager()->availableChannelGroups(false)) {
for(const auto& group : server->group_manager()->availableChannelGroups(false)) {
cmd[index]["id"] = group->groupId();
cmd[index]["name"] = group->name();
if(!writePermissions(group->permissions(), cmd, index, version, permission::teamspeak::SERVER, error)) break;

View File

@ -267,7 +267,7 @@ void VirtualServer::testBanStateChange(const std::shared_ptr<ConnectedClient>& i
bool VirtualServer::could_default_create_channel() {
{
auto default_group = this->getGroupManager()->defaultGroup(GroupTarget::GROUPTARGET_SERVER);
auto default_group = this->group_manager()->defaultGroup(GroupTarget::GROUPTARGET_SERVER);
if(default_group) {
auto flag = default_group->permissions()->permission_value_flagged(permission::b_channel_create_temporary).value == 1;
flag = flag ? flag : default_group->permissions()->permission_value_flagged(permission::b_channel_create_semi_permanent).value == 1;
@ -278,7 +278,7 @@ bool VirtualServer::could_default_create_channel() {
}
{
auto default_group = this->getGroupManager()->defaultGroup(GroupTarget::GROUPTARGET_CHANNEL);
auto default_group = this->group_manager()->defaultGroup(GroupTarget::GROUPTARGET_CHANNEL);
if(default_group) {
auto flag = default_group->permissions()->permission_value_flagged(permission::b_channel_create_temporary).value == 1;
flag = flag ? flag : default_group->permissions()->permission_value_flagged(permission::b_channel_create_semi_permanent).value == 1;

View File

@ -236,7 +236,7 @@ void VirtualServer::executeServerTick() {
{
BEGIN_TIMINGS();
auto groups = this->getGroupManager()->availableGroups(false);
auto groups = this->group_manager()->availableGroups(false);
for(auto& group : groups) {
auto permissions = group->permissions();
if(permissions->require_db_updates()) {

View File

@ -27,6 +27,7 @@
#include "src/manager/ConversationManager.h"
#include <misc/sassert.h>
#include <src/manager/ActionLogger.h>
#include "./groups/GroupManager.h"
using namespace std;
using namespace std::chrono;
@ -48,6 +49,7 @@ VirtualServer::VirtualServer(uint16_t serverId, sql::SqlManager* database) : ser
bool VirtualServer::initialize(bool test_properties) {
assert(self.lock());
std::string error{};
this->rtc_server_ = std::make_unique<rtc::Server>();
this->_properties = serverInstance->databaseHelper()->loadServerProperties(self.lock());
@ -187,9 +189,9 @@ bool VirtualServer::initialize(bool test_properties) {
channelTree = new ServerChannelTree(self.lock(), this->sql);
channelTree->loadChannelsFromDatabase();
this->groups = new GroupManager(self.lock(), this->sql, serverInstance->getOldGroupManager());
if(!this->groups->loadGroupFormDatabase()){ //TODO exception etc
logCritical(this->serverId, "Cant setup group manager!");
this->groups_manager_ = std::make_shared<groups::GroupManager>(this->getSql(), this->getServerId(), serverInstance->group_manager());
if(!this->groups_manager_->initialize(this->groups_manager_, error)) {
logCritical(this->getServerId(), "Failed to initialize group manager: {}", error);
return false;
}
@ -225,21 +227,57 @@ bool VirtualServer::initialize(bool test_properties) {
this->complains = new ComplainManager(this);
if(!this->complains->loadComplains()) logError(this->serverId, "Could not load complains");
//Setup new server if needed
if(this->groups->availableServerGroups(false).empty() || this->groups->availableChannelGroups(false).empty()){
if(!this->properties()[property::VIRTUALSERVER_AUTOGENERATED_PRIVILEGEKEY].as<string>().empty()) {
logCritical(this->getServerId(), "Missing default groups. Applying permission reset!");
{
using groups::GroupLoadResult;
bool initialize_groups{false};
switch(this->groups_manager_->server_groups()->load_data(true)) {
case GroupLoadResult::SUCCESS:
break;
case GroupLoadResult::NO_GROUPS:
initialize_groups = true;
break;
case GroupLoadResult::DATABASE_ERROR:
logError(this->getServerId(), "Failed to load server groups (Database error)");
return false;
}
switch(this->groups_manager_->channel_groups()->load_data(true)) {
case GroupLoadResult::SUCCESS:
break;
case GroupLoadResult::NO_GROUPS:
initialize_groups = true;
break;
case GroupLoadResult::DATABASE_ERROR:
logError(this->getServerId(), "Failed to load channel groups (Database error)");
return false;
}
if(!this->groups_manager_->assignments().load_data(error)) {
logError(this->getServerId(), "Failed to load group assignments: {}", error);
return false;
}
if (initialize_groups) {
if(!this->properties()[property::VIRTUALSERVER_AUTOGENERATED_PRIVILEGEKEY].as<string>().empty()) {
logCritical(this->getServerId(), "Missing default groups. Applying permission reset!");
}
string token;
if(!this->resetPermissions(token)) {
logCritical(this->serverId, "Failed to reset server permissions! This could be fatal!");
}
logMessageFmt(true, this->serverId, "---------------------- Token ----------------------");
logMessageFmt(true, this->serverId, "{:^51}", "The server's serveradmin token:");
logMessageFmt(true, this->serverId, "{:^51}", token);
logMessageFmt(true, this->serverId, "");
logMessageFmt(true, this->serverId, "{:^51}", "Note: This token could be used just once!");
logMessageFmt(true, this->serverId, "---------------------- Token ----------------------");
}
string token;
if(!this->resetPermissions(token))
logCritical(this->serverId, "Failed to reset server permissions! This could be fatal!");
logMessageFmt(true, this->serverId, "---------------------- Token ----------------------");
logMessageFmt(true, this->serverId, "{:^51}", "The server's serveradmin token:");
logMessageFmt(true, this->serverId, "{:^51}", token);
logMessageFmt(true, this->serverId, "");
logMessageFmt(true, this->serverId, "{:^51}", "Note: This token could be used just once!");
logMessageFmt(true, this->serverId, "---------------------- Token ----------------------");
}
if(test_properties)
this->ensureValidDefaultGroups();
@ -839,7 +877,7 @@ void VirtualServer::broadcastMessage(std::shared_ptr<ConnectedClient> invoker, s
std::vector<std::shared_ptr<GroupAssignment>> CalculateCache::getGroupAssignments(VirtualServer* server, ClientDbId cldbid, ClientType type) {
if(assignment_server_groups_set) return assignment_server_groups;
assignment_server_groups = server->getGroupManager()->getServerGroups(cldbid, type);
assignment_server_groups = server->group_manager()->getServerGroups(cldbid, type);
assignment_server_groups_set = true;
return assignment_server_groups;
}
@ -848,7 +886,7 @@ std::shared_ptr<GroupAssignment> CalculateCache::getChannelAssignment(VirtualSer
if(this->assignment_channel_group_set && this->assignment_channel_group_channel == channel_id) return this->assignment_channel_group;
auto channel = this->getServerChannel(server, channel_id);
assignment_channel_group = channel ? server->getGroupManager()->getChannelGroup(client_dbid, channel, true) : nullptr;
assignment_channel_group = channel ? server->group_manager()->getChannelGroup(client_dbid, channel, true) : nullptr;
assignment_channel_group_set = true;
assignment_channel_group_channel = channel_id;
return assignment_channel_group;
@ -884,7 +922,7 @@ vector<pair<ts::permission::PermissionType, ts::permission::v2::PermissionFlagge
}
if(!cache->client_permissions) {
cache->client_permissions = serverInstance->databaseHelper()->loadClientPermissionManager(self.lock(), client_dbid);
cache->client_permissions = serverInstance->databaseHelper()->loadClientPermissionManager(this->getServerId(), client_dbid);
}
bool have_skip_permission = false;
@ -1134,44 +1172,44 @@ bool VirtualServer::resetPermissions(std::string& new_permission_token) {
{
threads::MutexLock lock(this->getGroupManager()->cacheLock);
this->getGroupManager()->deleteAllGroups();
threads::MutexLock lock(this->group_manager()->cacheLock);
this->group_manager()->deleteAllGroups();
deque<shared_ptr<Group>> saved_groups;
for(const auto& group : serverInstance->getOldGroupManager()->availableGroups(false)){
for(const auto& group : serverInstance->group_manager()->availableGroups(false)){
if(group->type() != GroupType::GROUP_TYPE_TEMPLATE) continue;
debugMessage(this->serverId, "Copy default group {{Id: {}, Type: {}, Target: {}, Name: {}}} to server", group->groupId(), group->type(), group->target(), group->name());
this->getGroupManager()->copyGroup(group, GroupType::GROUP_TYPE_NORMAL, group->name(), this->serverId);
this->group_manager()->copyGroup(group, GroupType::GROUP_TYPE_NORMAL, group->name(), this->serverId);
}
}
//Server admin
auto default_server_admin = serverInstance->getOldGroupManager()->findGroup(serverInstance->properties()[property::SERVERINSTANCE_TEMPLATE_SERVERADMIN_GROUP].as<GroupId>());
auto default_server_music = serverInstance->getOldGroupManager()->findGroup(serverInstance->properties()[property::SERVERINSTANCE_TEMPLATE_MUSICDEFAULT_GROUP].as<GroupId>());
auto default_server_guest = serverInstance->getOldGroupManager()->findGroup(serverInstance->properties()[property::SERVERINSTANCE_TEMPLATE_SERVERDEFAULT_GROUP].as<GroupId>());
auto default_server_admin = serverInstance->group_manager()->findGroup(serverInstance->properties()[property::SERVERINSTANCE_TEMPLATE_SERVERADMIN_GROUP].as<GroupId>());
auto default_server_music = serverInstance->group_manager()->findGroup(serverInstance->properties()[property::SERVERINSTANCE_TEMPLATE_MUSICDEFAULT_GROUP].as<GroupId>());
auto default_server_guest = serverInstance->group_manager()->findGroup(serverInstance->properties()[property::SERVERINSTANCE_TEMPLATE_SERVERDEFAULT_GROUP].as<GroupId>());
auto default_channel_admin = serverInstance->getOldGroupManager()->findGroup(serverInstance->properties()[property::SERVERINSTANCE_TEMPLATE_CHANNELADMIN_GROUP].as<GroupId>());
auto default_channel_guest = serverInstance->getOldGroupManager()->findGroup(serverInstance->properties()[property::SERVERINSTANCE_TEMPLATE_CHANNELDEFAULT_GROUP].as<GroupId>());
auto default_channel_admin = serverInstance->group_manager()->findGroup(serverInstance->properties()[property::SERVERINSTANCE_TEMPLATE_CHANNELADMIN_GROUP].as<GroupId>());
auto default_channel_guest = serverInstance->group_manager()->findGroup(serverInstance->properties()[property::SERVERINSTANCE_TEMPLATE_CHANNELDEFAULT_GROUP].as<GroupId>());
if(!default_server_guest) {
logCritical(0, "Missing default server guest template group!");
assert(!serverInstance->getOldGroupManager()->availableChannelGroups().empty());
assert(!serverInstance->group_manager()->availableChannelGroups().empty());
default_server_guest = serverInstance->getOldGroupManager()->availableServerGroups().front();
default_server_guest = serverInstance->group_manager()->availableServerGroups().front();
logCritical(0, "Using group {} as default server guest group for server {}.", default_server_guest->name(), this->serverId);
}
if(!default_channel_admin) {
logCritical(0, "Missing default channel guest template group!");
assert(!serverInstance->getOldGroupManager()->availableChannelGroups().empty());
assert(!serverInstance->group_manager()->availableChannelGroups().empty());
default_channel_admin = serverInstance->getOldGroupManager()->availableChannelGroups().front();
default_channel_admin = serverInstance->group_manager()->availableChannelGroups().front();
logCritical(0, "Using group {} as channel server guest group for server {}.", default_channel_admin->name(), this->serverId);
}
if(!default_server_music) {
logCritical(0, "Missing default channel guest template group!");
assert(!serverInstance->getOldGroupManager()->availableChannelGroups().empty());
assert(!serverInstance->group_manager()->availableChannelGroups().empty());
default_server_music = serverInstance->getOldGroupManager()->availableChannelGroups().front();
default_server_music = serverInstance->group_manager()->availableChannelGroups().front();
logCritical(0, "Using group {} as channel server guest group for server {}.", default_server_music->name(), this->serverId);
}
@ -1185,12 +1223,12 @@ bool VirtualServer::resetPermissions(std::string& new_permission_token) {
default_channel_admin = default_channel_guest;
}
this->properties()[property::VIRTUALSERVER_DEFAULT_SERVER_GROUP] = this->getGroupManager()->findGroup(GroupTarget::GROUPTARGET_SERVER, default_server_guest->name()).front()->groupId();
this->properties()[property::VIRTUALSERVER_DEFAULT_MUSIC_GROUP] = this->getGroupManager()->findGroup(GroupTarget::GROUPTARGET_SERVER, default_server_music->name()).front()->groupId();
this->properties()[property::VIRTUALSERVER_DEFAULT_CHANNEL_ADMIN_GROUP] = this->getGroupManager()->findGroup(GroupTarget::GROUPTARGET_CHANNEL, default_channel_admin->name()).front()->groupId();
this->properties()[property::VIRTUALSERVER_DEFAULT_CHANNEL_GROUP] = this->getGroupManager()->findGroup(GroupTarget::GROUPTARGET_CHANNEL, default_channel_guest->name()).front()->groupId();
this->properties()[property::VIRTUALSERVER_DEFAULT_SERVER_GROUP] = this->group_manager()->findGroup(GroupTarget::GROUPTARGET_SERVER, default_server_guest->name()).front()->groupId();
this->properties()[property::VIRTUALSERVER_DEFAULT_MUSIC_GROUP] = this->group_manager()->findGroup(GroupTarget::GROUPTARGET_SERVER, default_server_music->name()).front()->groupId();
this->properties()[property::VIRTUALSERVER_DEFAULT_CHANNEL_ADMIN_GROUP] = this->group_manager()->findGroup(GroupTarget::GROUPTARGET_CHANNEL, default_channel_admin->name()).front()->groupId();
this->properties()[property::VIRTUALSERVER_DEFAULT_CHANNEL_GROUP] = this->group_manager()->findGroup(GroupTarget::GROUPTARGET_CHANNEL, default_channel_guest->name()).front()->groupId();
auto server_admin_group_id = this->getGroupManager()->findGroup(GroupTarget::GROUPTARGET_SERVER, default_server_admin->name()).front()->groupId();
auto server_admin_group_id = this->group_manager()->findGroup(GroupTarget::GROUPTARGET_SERVER, default_server_admin->name()).front()->groupId();
auto token = this->tokenManager->create_token(0, "Default server admin token", 1, std::chrono::system_clock::time_point{});
if(!token) {
logCritical(this->serverId, "Failed to register the default server admin token.");
@ -1217,7 +1255,7 @@ bool VirtualServer::resetPermissions(std::string& new_permission_token) {
client->notifyServerGroupList();
client->notifyChannelGroupList();
}
if(this->notifyClientPropertyUpdates(client, this->getGroupManager()->update_server_group_property(client, true, client->getChannel()))) {
if(this->notifyClientPropertyUpdates(client, this->group_manager()->update_server_group_property(client, true, client->getChannel()))) {
client->task_update_needed_permissions.enqueue();
}
client->task_update_channel_client_properties.enqueue();
@ -1226,16 +1264,16 @@ bool VirtualServer::resetPermissions(std::string& new_permission_token) {
}
void VirtualServer::ensureValidDefaultGroups() {
auto default_server_group = this->getGroupManager()->defaultGroup(GROUPTARGET_SERVER, true);
auto default_server_group = this->group_manager()->defaultGroup(GROUPTARGET_SERVER, true);
if(!default_server_group) {
logError(this->serverId, "Missing server's default server group! (Id: {})", this->properties()[property::VIRTUALSERVER_DEFAULT_SERVER_GROUP].value());
default_server_group = this->getGroupManager()->availableServerGroups(false).front();
default_server_group = this->group_manager()->availableServerGroups(false).front();
logError(this->serverId, "Using {} ({}) instead!", default_server_group->groupId(), default_server_group->name());
this->properties()[property::VIRTUALSERVER_DEFAULT_SERVER_GROUP] = default_server_group->groupId();
}
auto default_music_group = this->getGroupManager()->defaultGroup(GROUPTARGET_SERVER, true);
auto default_music_group = this->group_manager()->defaultGroup(GROUPTARGET_SERVER, true);
if(!default_music_group) {
logError(this->serverId, "Missing server's default music group! (Id: {})", this->properties()[property::VIRTUALSERVER_DEFAULT_MUSIC_GROUP].value());
@ -1244,20 +1282,20 @@ void VirtualServer::ensureValidDefaultGroups() {
this->properties()[property::VIRTUALSERVER_DEFAULT_MUSIC_GROUP] = default_music_group->groupId();
}
auto default_channel_group = this->getGroupManager()->defaultGroup(GROUPTARGET_CHANNEL, true);
auto default_channel_group = this->group_manager()->defaultGroup(GROUPTARGET_CHANNEL, true);
if(!default_channel_group) {
logError(this->serverId, "Missing server's default channel group! (Id: {})", this->properties()[property::VIRTUALSERVER_DEFAULT_CHANNEL_GROUP].value());
default_channel_group = this->getGroupManager()->availableChannelGroups(false).front();
default_channel_group = this->group_manager()->availableChannelGroups(false).front();
logError(this->serverId, "Using {} ({}) instead!", default_channel_group->groupId(), default_channel_group->name());
this->properties()[property::VIRTUALSERVER_DEFAULT_CHANNEL_GROUP] = default_channel_group->groupId();
}
auto admin_channel_group = this->getGroupManager()->findGroupLocal(this->properties()[property::VIRTUALSERVER_DEFAULT_CHANNEL_ADMIN_GROUP].as_save<GroupId>());
auto admin_channel_group = this->group_manager()->findGroupLocal(this->properties()[property::VIRTUALSERVER_DEFAULT_CHANNEL_ADMIN_GROUP].as_save<GroupId>());
if(!admin_channel_group) {
logError(this->serverId, "Missing server's default channel admin group! (Id: {})", this->properties()[property::VIRTUALSERVER_DEFAULT_CHANNEL_ADMIN_GROUP].value());
admin_channel_group = this->getGroupManager()->availableChannelGroups(false).front();
admin_channel_group = this->group_manager()->availableChannelGroups(false).front();
logError(this->serverId, "Using {} ({}) instead!", admin_channel_group->groupId(), admin_channel_group->name());
this->properties()[property::VIRTUALSERVER_DEFAULT_CHANNEL_ADMIN_GROUP] = admin_channel_group->groupId();
}
@ -1347,4 +1385,16 @@ void VirtualServer::update_channel_from_permissions(const std::shared_ptr<BasicC
}
});
}
}
std::shared_ptr<groups::ChannelGroup> VirtualServer::default_channel_group() {
auto group_id = this->properties()[property::VIRTUALSERVER_DEFAULT_CHANNEL_GROUP].as_save<GroupId>();
auto group = this->group_manager()->channel_groups()->find_group(groups::GroupCalculateMode::GLOBAL, group_id);
if(!group) {
auto groups = this->group_manager()->channel_groups()->available_groups(groups::GroupCalculateMode::GLOBAL);
/* TODO: Log warning? */
group = groups.back();
}
return group;
}

View File

@ -67,11 +67,15 @@ namespace ts {
class WebControlServer;
namespace conversation {
class ConversationManager;
}
namespace groups {
class ChannelGroup;
class GroupManager;
}
struct ServerState {
enum value {
OFFLINE,
@ -188,13 +192,15 @@ namespace ts {
inline ServerId getServerId(){ return this->serverId; }
inline ServerChannelTree* getChannelTree(){ return this->channelTree; }
inline GroupManager* getGroupManager() { return this->groups; }
inline rtc::Server& rtc_server() { return *this->rtc_server_; }
[[nodiscard]] inline auto& getTokenManager() {
return *this->tokenManager;
}
[[nodiscard]] inline auto group_manager() { return this->groups_manager_; }
[[nodiscard]] std::shared_ptr<groups::ChannelGroup> default_channel_group();
bool notifyServerEdited(std::shared_ptr<ConnectedClient>, std::deque<std::string> keys);
bool notifyClientPropertyUpdates(std::shared_ptr<ConnectedClient>, const std::deque<const property::PropertyDescription*>& keys, bool selfNotify = true); /* execute only with at least channel tree read lock! */
inline bool notifyClientPropertyUpdates(const std::shared_ptr<ConnectedClient>& client, const std::deque<property::ClientProperties>& keys, bool selfNotify = true) {
@ -343,7 +349,7 @@ namespace ts {
ServerChannelTree* channelTree = nullptr;
std::shared_mutex channel_tree_lock; /* lock if access channel tree! */
GroupManager* groups = nullptr;
std::shared_ptr<groups::GroupManager> groups_manager_{};
std::shared_ptr<ConnectedClient> serverRoot = nullptr;
std::shared_ptr<ConnectedClient> serverAdmin = nullptr;

View File

@ -574,11 +574,11 @@ void ServerChannelTree::on_channel_entry_deleted(const shared_ptr<BasicChannel>
auto server = this->server_ref.lock();
if(server) {
server->getGroupManager()->handleChannelDeleted(channel->channelId());
server->group_manager()->handleChannelDeleted(channel->channelId());
server->conversation_manager()->delete_conversation(channel->channelId());
server->rtc_server().destroy_channel(server_channel->rtc_channel_id);
} else {
serverInstance->getOldGroupManager()->handleChannelDeleted(channel->channelId());
serverInstance->group_manager()->handleChannelDeleted(channel->channelId());
}

View File

@ -11,6 +11,9 @@
#include "src/VirtualServer.h"
#include "voice/VoiceClient.h"
#include "../InstanceHandler.h"
#include "../PermissionCalculator.h"
#include "../groups/GroupManager.h"
#include "../groups/Group.h"
#include <event.h>
using namespace std;
@ -119,8 +122,6 @@ void ConnectedClient::updateChannelClientProperties(bool lock_channel_tree, bool
permission::b_client_ignore_antiflood,
permission::i_channel_view_power,
permission::b_channel_ignore_view_power,
permission::i_icon_id,
permission::b_client_is_priority_speaker,
}, channel ? channel->channelId() : 0);
permission::v2::PermissionFlaggedValue
@ -974,7 +975,9 @@ bool ConnectedClient::update_client_needed_permissions() {
/* The server and/or the channel might change while we're executing this method */
auto currentChannel = this->currentChannel;
auto values = this->calculate_permissions(permission::neededPermissions, currentChannel ? currentChannel->channelId() : 0);
ClientPermissionCalculator permission_helper{this, currentChannel};
auto values = permission_helper.calculate_permissions(permission::neededPermissions);
auto updated = false;
{
@ -1072,6 +1075,9 @@ permission::PermissionType ConnectedClient::calculate_and_get_join_state(const s
}
void ConnectedClient::useToken(token::TokenId token_id) {
using groups::GroupCalculateMode;
using groups::GroupAssignmentResult;
auto server_ref = this->server;
if(!server_ref) {
return;
@ -1089,38 +1095,56 @@ void ConnectedClient::useToken(token::TokenId token_id) {
bool tree_registered = !!this->currentChannel;
bool server_groups_changed{false}, channel_group_changed{false};
std::deque<std::shared_ptr<Group>> added_server_groups{};
std::deque<std::shared_ptr<Group>> removed_server_groups{};
std::deque<std::shared_ptr<groups::ServerGroup>> added_server_groups{};
std::deque<std::shared_ptr<groups::ServerGroup>> removed_server_groups{};
for(const auto& action : actions) {
switch(action.type) {
case token::ActionType::AddServerGroup:
case token::ActionType::RemoveServerGroup: {
auto group = server->getGroupManager()->findGroup(action.id1);
if(!group || group->target() != GroupTarget::GROUPTARGET_SERVER) {
auto group = server->group_manager()->server_groups()->find_group(GroupCalculateMode::GLOBAL, action.id1);
if(!group) {
debugMessage(this->getServerId(), "{} Skipping token action add/remove server group for group {} because the group does not exists anymore.", CLIENT_STR_LOG_PREFIX, action.id1);
break;
}
if(action.type == token::ActionType::AddServerGroup) {
if(this->server->groups->hasServerGroupAssigned(this->getClientDatabaseId(), group)) {
debugMessage(this->getServerId(), "{} Skipping token action add server group for group {} because client is already member of that group.", CLIENT_STR_LOG_PREFIX, action.id1);
} else {
debugMessage(this->getServerId(), "{} Executing token action add server group for group {}.", CLIENT_STR_LOG_PREFIX, action.id1);
this->server->groups->addServerGroup(this->getClientDatabaseId(), group);
auto result = this->server->group_manager()->assignments().add_server_group(this->getClientDatabaseId(), group->group_id());
switch(result) {
case GroupAssignmentResult::SUCCESS:
debugMessage(this->getServerId(), "{} Executing token action add server group for group {}.", CLIENT_STR_LOG_PREFIX, action.id1);
added_server_groups.push_back(group);
server_groups_changed = true;
break;
added_server_groups.push_back(group);
server_groups_changed = true;
case GroupAssignmentResult::ADD_ALREADY_MEMBER_OF_GROUP:
debugMessage(this->getServerId(), "{} Skipping token action add server group for group {} because client is already member of that group.", CLIENT_STR_LOG_PREFIX, action.id1);
break;
case GroupAssignmentResult::REMOVE_NOT_MEMBER_OF_GROUP:
case GroupAssignmentResult::SET_ALREADY_MEMBER_OF_GROUP:
default:
assert(false);
break;
}
} else {
if(!this->server->groups->hasServerGroupAssigned(this->getClientDatabaseId(), group)) {
debugMessage(this->getServerId(), "{} Skipping token action remove server group for group {} because client is not a member of that group.", CLIENT_STR_LOG_PREFIX, action.id1);
} else {
debugMessage(this->getServerId(), "{} Executing token action remove server group for group {}.", CLIENT_STR_LOG_PREFIX, action.id1);
this->server->groups->removeServerGroup(this->getClientDatabaseId(), group);
auto result = this->server->group_manager()->assignments().remove_server_group(this->getClientDatabaseId(), group->group_id());
switch(result) {
case GroupAssignmentResult::SUCCESS:
debugMessage(this->getServerId(), "{} Executing token action remove server group for group {}.", CLIENT_STR_LOG_PREFIX, action.id1);
removed_server_groups.push_back(group);
server_groups_changed = true;
break;
removed_server_groups.push_back(group);
server_groups_changed = true;
case GroupAssignmentResult::REMOVE_NOT_MEMBER_OF_GROUP:
debugMessage(this->getServerId(), "{} Skipping token action remove server group for group {} because client is not a member of that group.", CLIENT_STR_LOG_PREFIX, action.id1);
break;
case GroupAssignmentResult::ADD_ALREADY_MEMBER_OF_GROUP:
case GroupAssignmentResult::SET_ALREADY_MEMBER_OF_GROUP:
default:
assert(false);
break;
}
}
@ -1128,8 +1152,8 @@ void ConnectedClient::useToken(token::TokenId token_id) {
}
case token::ActionType::SetChannelGroup: {
auto group = server->getGroupManager()->findGroup(action.id1);
if(!group || group->target() != GroupTarget::GROUPTARGET_CHANNEL) {
auto group = server->group_manager()->channel_groups()->find_group(GroupCalculateMode::GLOBAL, action.id1);
if(!group) {
debugMessage(this->getServerId(), "{} Skipping token action set channel group for group {} at channel {} because the group does not exists anymore.", CLIENT_STR_LOG_PREFIX, action.id1, action.id2);
break;
}
@ -1141,7 +1165,7 @@ void ConnectedClient::useToken(token::TokenId token_id) {
}
channel_group_changed = true;
this->server->groups->setChannelGroup(this->getClientDatabaseId(), group, channel);
this->server->group_manager()->assignments().set_channel_group(this->getClientDatabaseId(), group->group_id(), channel->channelId(), !group->is_permanent());
break;
}
@ -1167,7 +1191,8 @@ void ConnectedClient::useToken(token::TokenId token_id) {
}
if(tree_registered && (server_groups_changed || channel_group_changed)) {
auto updated_properties = this->getServer()->getGroupManager()->update_server_group_property(this->ref(), true, this->currentChannel);
/* TODO: Set "Update server groups" as task */
auto updated_properties = this->getServer()->group_manager()->update_server_group_property(this->ref(), true, this->currentChannel);
if(!updated_properties.empty()) {
this->getServer()->notifyClientPropertyUpdates(this->ref(), updated_properties);
}

View File

@ -47,7 +47,6 @@ do {\
if(cmd.bulkCount() != count) return command_result{error::parameter_invalid_count};
namespace ts {
class GroupManager;
namespace connection {
class VoiceClientConnection;
}
@ -108,8 +107,6 @@ namespace ts {
inline std::shared_ptr<BasicChannel> getChannel(){ return this->currentChannel; }
inline ChannelId getChannelId(){ auto channel = this->currentChannel; return channel ? channel->channelId() : 0; }
inline std::shared_ptr<VirtualServer> getServer(){ return this->server; }
inline ServerId getServerId(){ return this->server ? this->server->getServerId() : (ServerId) 0; }
//bool channelSubscribed(const std::shared_ptr<BasicChannel>&);
/* if lock_channel == false then channel_lock must be write locked! */

View File

@ -45,7 +45,7 @@ bool ConnectedClient::notifyServerGroupList(bool as_notify) {
Command cmd(as_notify ? "notifyservergrouplist" : "");
int index = 0;
for (const auto& group : (this->server ? this->server->groups : serverInstance->getOldGroupManager().get())->availableServerGroups(true)) {
for (const auto& group : (this->server ? this->server->group_manager() : serverInstance->group_manager().get())->availableServerGroups(true)) {
if(group->target() == GroupTarget::GROUPTARGET_CHANNEL) {
cmd[index]["cgid"] = group->groupId();
} else {
@ -171,7 +171,7 @@ bool ConnectedClient::notifyClientPermList(ClientDbId cldbid, const std::shared_
bool ConnectedClient::notifyChannelGroupList(bool as_notify) {
Command cmd(as_notify ? "notifychannelgrouplist" : "");
int index = 0;
for (const auto &group : (this->server ? this->server->groups : serverInstance->getOldGroupManager().get())->availableChannelGroups(true)) {
for (const auto &group : (this->server ? this->server->group_manager() : serverInstance->group_manager().get())->availableChannelGroups(true)) {
if(group->target() == GroupTarget::GROUPTARGET_CHANNEL) {
cmd[index]["cgid"] = group->groupId();
} else {

View File

@ -5,6 +5,7 @@
#include "./DataClient.h"
#include "../InstanceHandler.h"
#include "../groups/GroupManager.h"
using namespace std;
using namespace ts;
@ -89,8 +90,9 @@ bool DataClient::loadDataForCurrentServer() {
}
});
if(this->properties()[property::CLIENT_DATABASE_ID].as<ClientDbId>() == 0)
if(this->properties()[property::CLIENT_DATABASE_ID].as<ClientDbId>() == 0) {
return false;
}
//Load general properties
std::deque<ts::PropertyWrapper> copied;
@ -117,7 +119,7 @@ bool DataClient::loadDataForCurrentServer() {
}
this->_properties->toggleSave(true);
this->clientPermissions = serverInstance->databaseHelper()->loadClientPermissionManager(ref_server, this->getClientDatabaseId());
this->clientPermissions = serverInstance->databaseHelper()->loadClientPermissionManager(ref_server->getServerId(), this->getClientDatabaseId());
//Setup / fix stuff
#if 0
@ -165,39 +167,81 @@ std::vector<std::pair<permission::PermissionType, permission::v2::PermissionFlag
if(ref_server) {
return ref_server->calculate_permissions(permissions, this->getClientDatabaseId(), this->getType(), channel, granted, cache);
} else {
return serverInstance->calculate_permissions(permissions, this->getClientDatabaseId(), this->getType(), channel, granted, cache);
return serverInstance->permission_helper().calculate_permissions(permissions, this->getClientDatabaseId(), this->getType(), channel, granted, cache);
}
}
permission::v2::PermissionFlaggedValue DataClient::calculate_permission(
permission::PermissionType permission, ChannelId channel, bool granted, std::shared_ptr<CalculateCache> cache) {
auto result = this->calculate_permissions({permission}, channel, granted, cache);
if(result.empty()) return {0, false};
if(result.empty()) {
return {0, false};
}
return result.back().second;
}
std::vector<std::shared_ptr<GroupAssignment>> DataClient::assignedServerGroups() {
if(!this->server) return serverInstance->getOldGroupManager()->getServerGroups(this->getClientDatabaseId(), this->getType());
return this->server->groups->getServerGroups(this->getClientDatabaseId(), this->getType());
std::vector<std::shared_ptr<groups::ServerGroup>> DataClient::assignedServerGroups() {
auto ref_server = this->server;
auto group_manager = ref_server ? ref_server->group_manager() : serverInstance->group_manager();
auto assignments = group_manager->assignments().server_groups_of_client(groups::GroupAssignmentCalculateMode::GLOBAL, this->getClientDatabaseId());
std::vector<std::shared_ptr<groups::ServerGroup>> result{};
result.reserve(assignments.size());
for(const auto& group_id : assignments) {
auto group = group_manager->server_groups()->find_group(groups::GroupCalculateMode::GLOBAL, group_id);
if(group) {
result.push_back(group);
}
}
return result;
}
std::shared_ptr<GroupAssignment> DataClient::assignedChannelGroup(const shared_ptr<BasicChannel> &channel) {
if(!this->server || !channel) return {};
return this->server->groups->getChannelGroup(this->getClientDatabaseId(), channel, true);
std::shared_ptr<groups::ChannelGroup> DataClient::assignedChannelGroup(const shared_ptr<BasicChannel> &channel) {
auto ref_server = this->server;
assert(channel);
if(!channel || !ref_server) {
return nullptr;
}
std::shared_ptr<groups::ChannelGroup> result{};
auto group_manager = ref_server ? ref_server->group_manager() : serverInstance->group_manager();
auto channel_group_assignment = group_manager->assignments().channel_group_of_client(groups::GroupAssignmentCalculateMode::GLOBAL, this->getClientDatabaseId(), channel->channelId());
if(channel_group_assignment.has_value()) {
result = group_manager->channel_groups()->find_group(groups::GroupCalculateMode::GLOBAL, channel_group_assignment->group_id);
}
if(!result) {
result = ref_server->default_channel_group();
}
assert(result);
return result;
}
bool DataClient::serverGroupAssigned(const shared_ptr<Group> &group) {
for(const auto &gr : this->assignedServerGroups())
if(gr->group == group) return true;
bool DataClient::serverGroupAssigned(const shared_ptr<groups::ServerGroup> &group) {
auto ref_server = this->server;
auto group_manager = ref_server ? ref_server->group_manager() : serverInstance->group_manager();
auto assignments = group_manager->assignments().server_groups_of_client(groups::GroupAssignmentCalculateMode::GLOBAL, this->getClientDatabaseId());
for(const auto& assigned_group_id : assignments) {
if(assigned_group_id == group->group_id()) {
return true;
}
}
return false;
}
bool DataClient::channelGroupAssigned(const shared_ptr<Group> &group, const shared_ptr<BasicChannel> &channel) {
if(!channel) return false;
auto gr = this->assignedChannelGroup(channel);
sassert(gr);
if(!gr) return false;
return gr->group == group;
bool DataClient::channelGroupAssigned(const shared_ptr<groups::ChannelGroup> &group, const shared_ptr<BasicChannel> &channel) {
if(!channel) {
return false;
}
return this->assignedChannelGroup(channel) == group;
}
std::string DataClient::getAvatarId() {

View File

@ -19,6 +19,11 @@ namespace ts {
namespace server {
class VirtualServer;
namespace groups {
class ServerGroup;
class ChannelGroup;
}
class DataClient {
friend class VirtualServer;
friend class QueryServer;
@ -63,6 +68,7 @@ namespace ts {
PropertyWrapper properties(){ return { this->_properties }; }
[[nodiscard]] inline auto permissions(){ return this->clientPermissions; }
/* main permission calculate function */
/**
@ -95,15 +101,20 @@ namespace ts {
std::shared_ptr<CalculateCache> cache = nullptr
);
virtual std::vector<std::shared_ptr<GroupAssignment>> assignedServerGroups();
virtual std::shared_ptr<GroupAssignment> assignedChannelGroup(const std::shared_ptr<BasicChannel> &);
virtual bool serverGroupAssigned(const std::shared_ptr<Group> &);
virtual bool channelGroupAssigned(const std::shared_ptr<Group> &, const std::shared_ptr<BasicChannel> &);
virtual std::vector<std::shared_ptr<groups::ServerGroup>> assignedServerGroups();
virtual std::shared_ptr<groups::ChannelGroup> assignedChannelGroup(const std::shared_ptr<BasicChannel> &);
virtual bool serverGroupAssigned(const std::shared_ptr<groups::ServerGroup> &);
virtual bool channelGroupAssigned(const std::shared_ptr<groups::ChannelGroup> &, const std::shared_ptr<BasicChannel> &);
virtual std::string getDisplayName() { return this->properties()[property::CLIENT_NICKNAME]; }
virtual std::string getLoginName() { return this->properties()[property::CLIENT_LOGIN_NAME]; }
virtual void setDisplayName(std::string displayName) { this->properties()[property::CLIENT_NICKNAME] = displayName; }
[[nodiscard]] inline std::shared_ptr<VirtualServer> getServer() { return this->server; }
[[nodiscard]] inline ServerId getServerId() {
auto server_ref = this->getServer();
return server_ref ? server_ref->getServerId() : (ServerId) 0;
}
virtual ClientType getExternalType(){
uint8_t type = this->properties()[property::CLIENT_TYPE];

View File

@ -122,7 +122,7 @@ command_result SpeakingClient::handleCommandClientInit(Command& cmd) {
}
TIMING_STEP(timings, "db assign ");
this->server->getGroupManager()->enableCache(this->getClientDatabaseId());
this->server->group_manager()->enableCache(this->getClientDatabaseId());
TIMING_STEP(timings, "gr cache ");
const static vector<string> available_parameters = {
@ -437,9 +437,9 @@ void SpeakingClient::processJoin() {
}
TIMING_STEP(timings, "server reg ");
ref_server->getGroupManager()->cleanupAssignments(this->getClientDatabaseId());
ref_server->group_manager()->cleanupAssignments(this->getClientDatabaseId());
TIMING_STEP(timings, "grp cleanup");
ref_server->getGroupManager()->update_server_group_property(this->ref(), true, nullptr);
ref_server->group_manager()->update_server_group_property(this->ref(), true, nullptr);
TIMING_STEP(timings, "grp apply ");
this->properties()[property::CLIENT_COUNTRY] = config::geo::countryFlag;
@ -568,7 +568,7 @@ void SpeakingClient::processLeave() {
unique_lock server_channel_lock(this->server->channel_tree_lock);
server->unregisterClient(ownLock, "disconnected", server_channel_lock); /* already moves client to void if needed */
}
server->groups->disableCache(ownLock->getClientDatabaseId());
server->group_manager()->disableCache(ownLock->getClientDatabaseId());
server->music_manager_->cleanup_client_bots(this->getClientDatabaseId());
//ref_server = nullptr; Removed caused nullptr exceptions
}

View File

@ -136,7 +136,7 @@ command_result ConnectedClient::handleCommandChannelGroupAdd(Command &cmd) {
CMD_CHK_AND_INC_FLOOD_POINTS(5);
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_channelgroup_create, 1);
auto group_manager = this->server ? this->server->getGroupManager() : serverInstance->getOldGroupManager().get();
auto group_manager = this->server ? this->server->group_manager() : serverInstance->group_manager().get();
log::GroupType log_group_type;
if (cmd["type"].as<GroupType>() == GroupType::GROUP_TYPE_QUERY) {
@ -203,7 +203,7 @@ command_result ConnectedClient::handleCommandChannelGroupCopy(Command &cmd) {
auto ref_server = this->server;
auto group_manager = this->server ? this->server->groups : serverInstance->getOldGroupManager().get();
auto group_manager = this->server ? this->server->group_manager() : serverInstance->group_manager().get();
auto source_group_id = cmd["scgid"].as<GroupId>();
auto source_group = group_manager->findGroup(source_group_id);
@ -338,7 +338,7 @@ command_result ConnectedClient::handleCommandChannelGroupRename(Command &cmd) {
CMD_RESET_IDLE;
CMD_CHK_AND_INC_FLOOD_POINTS(5);
auto group_manager = this->server ? this->server->getGroupManager() : serverInstance->getOldGroupManager().get();
auto group_manager = this->server ? this->server->group_manager() : serverInstance->group_manager().get();
auto channel_group = group_manager->findGroup(cmd["cgid"].as<GroupId>());
if (!channel_group || channel_group->target() != GROUPTARGET_CHANNEL)
return command_result{error::parameter_invalid, "invalid channel group id"};
@ -373,7 +373,7 @@ command_result ConnectedClient::handleCommandChannelGroupDel(Command &cmd) {
CMD_CHK_AND_INC_FLOOD_POINTS(5);
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_channelgroup_delete, 1);
auto group_manager = this->server ? this->server->getGroupManager() : serverInstance->getOldGroupManager().get();
auto group_manager = this->server ? this->server->group_manager() : serverInstance->group_manager().get();
auto channel_group = group_manager->findGroup(cmd["cgid"].as<GroupId>());
if (!channel_group || channel_group->target() != GROUPTARGET_CHANNEL) return command_result{error::parameter_invalid, "invalid channel group id"};
@ -409,7 +409,7 @@ command_result ConnectedClient::handleCommandChannelGroupDel(Command &cmd) {
serverInstance->action_logger()->group_logger.log_group_delete(this->getServerId(), this->ref(), log::GroupTarget::SERVER, log_group_type, channel_group->groupId(), channel_group->name());
if (this->server) {
this->server->forEachClient([&](shared_ptr<ConnectedClient> cl) {
if (this->server->notifyClientPropertyUpdates(cl, this->server->groups->update_server_group_property(cl, true, cl->getChannel()))) {
if (this->server->notifyClientPropertyUpdates(cl, this->server->group_manager()->update_server_group_property(cl, true, cl->getChannel()))) {
cl->task_update_needed_permissions.enqueue();
}
cl->notifyChannelGroupList();
@ -450,7 +450,7 @@ command_result ConnectedClient::handleCommandChannelGroupClientList(Command &cmd
string query = "SELECT `groupId`, `cldbid`, `until`, `channelId` FROM `assignedGroups` WHERE `serverId` = :sid";
if (cmd[0].has("cgid") && cmd["cgid"].as<GroupId>() > 0) {
auto group = this->server->getGroupManager()->findGroup(cmd["cgid"]);
auto group = this->server->group_manager()->findGroup(cmd["cgid"]);
if (!group || group->target() != GroupTarget::GROUPTARGET_CHANNEL)
return command_result{error::parameter_invalid, "invalid channel group id"};
query += " AND `groupId` = :groupId";
@ -508,7 +508,7 @@ command_result ConnectedClient::handleCommandChannelGroupPermList(Command &cmd)
CMD_CHK_AND_INC_FLOOD_POINTS(5);
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_channelgroup_permission_list, 1);
auto channelGroup = (this->server ? this->server->groups : serverInstance->getOldGroupManager().get())->findGroup(cmd["cgid"].as<GroupId>());
auto channelGroup = (this->server ? this->server->group_manager() : serverInstance->group_manager().get())->findGroup(cmd["cgid"].as<GroupId>());
if (!channelGroup || channelGroup->target() != GROUPTARGET_CHANNEL) return command_result{error::parameter_invalid, "invalid channel group id"};
if (!this->notifyGroupPermList(channelGroup, cmd.hasParm("permsid"))) return command_result{error::database_empty_result};
@ -522,7 +522,7 @@ command_result ConnectedClient::handleCommandChannelGroupPermList(Command &cmd)
command_result ConnectedClient::handleCommandChannelGroupAddPerm(Command &cmd) {
CMD_CHK_AND_INC_FLOOD_POINTS(5);
auto group_manager = this->server ? this->server->getGroupManager() : serverInstance->getOldGroupManager().get();
auto group_manager = this->server ? this->server->group_manager() : serverInstance->group_manager().get();
auto channelGroup = group_manager->findGroup(cmd["cgid"].as<GroupId>());
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);
@ -574,7 +574,7 @@ command_result ConnectedClient::handleCommandChannelGroupAddPerm(Command &cmd) {
command_result ConnectedClient::handleCommandChannelGroupDelPerm(Command &cmd) {
CMD_CHK_AND_INC_FLOOD_POINTS(5);
auto group_manager = this->server ? this->server->getGroupManager() : serverInstance->getOldGroupManager().get();
auto group_manager = this->server ? this->server->group_manager() : serverInstance->group_manager().get();
auto channelGroup = group_manager->findGroup(cmd["cgid"].as<GroupId>());
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);
@ -954,14 +954,14 @@ command_result ConnectedClient::handleCommandChannelCreate(Command &cmd) {
const auto self_lock = this->ref();
GroupId adminGroup = this->server->properties()[property::VIRTUALSERVER_DEFAULT_CHANNEL_ADMIN_GROUP];
auto channel_admin_group = this->server->groups->findGroup(adminGroup);
auto channel_admin_group = this->server->group_manager()->findGroup(adminGroup);
if (!channel_admin_group) {
logError(this->getServerId(), "Missing server's default channel admin group! Using default channel group!");
channel_admin_group = this->server->groups->defaultGroup(GroupTarget::GROUPTARGET_CHANNEL);
channel_admin_group = this->server->group_manager()->defaultGroup(GroupTarget::GROUPTARGET_CHANNEL);
}
/* FIXME: Log group assignment */
this->server->groups->setChannelGroup(this->getClientDatabaseId(), channel_admin_group, created_channel);
this->server->group_manager()->setChannelGroup(this->getClientDatabaseId(), channel_admin_group, created_channel);
if (created_channel->channelType() == ChannelType::temporary && (this->getType() == ClientType::CLIENT_TEAMSPEAK || this->getType() == ClientType::CLIENT_WEB || this->getType() == ClientType::CLIENT_TEASPEAK)) {
channel_tree_read_lock.unlock();
@ -2264,7 +2264,7 @@ command_result ConnectedClient::handleCommandChannelClientPermList(Command &cmd)
ACTION_REQUIRES_PERMISSION(permission::b_virtualserver_channelclient_permission_list, 1, channel_id);
if (!serverInstance->databaseHelper()->validClientDatabaseId(this->server, cmd["cldbid"])) return command_result{error::client_invalid_id};
auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cmd["cldbid"].as<ClientDbId>());
auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->getServerId(), cmd["cldbid"].as<ClientDbId>());
Command res(this->getExternalType() == CLIENT_TEAMSPEAK ? "notifychannelclientpermlist" : "");
@ -2324,7 +2324,7 @@ command_result ConnectedClient::handleCommandChannelClientDelPerm(Command &cmd)
auto channel = dynamic_pointer_cast<ServerChannel>(l_channel->entry);
if (!channel) return command_result{error::vs_critical};
auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cldbid);
auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->getServerId(), 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);
@ -2393,7 +2393,7 @@ command_result ConnectedClient::handleCommandChannelClientAddPerm(Command &cmd)
auto channel = dynamic_pointer_cast<ServerChannel>(l_channel->entry);
if (!channel) return command_result{error::vs_critical};
auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cldbid);
auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->getServerId(), 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);

View File

@ -977,7 +977,7 @@ command_result ConnectedClient::handleCommandClientAddPerm(Command &cmd) {
auto cldbid = cmd["cldbid"].as<ClientDbId>();
if(!serverInstance->databaseHelper()->validClientDatabaseId(this->server, cldbid))
return command_result{error::client_invalid_id};
auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cldbid);
auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->getServerId(), 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));
@ -1021,7 +1021,7 @@ command_result ConnectedClient::handleCommandClientDelPerm(Command &cmd) {
auto cldbid = cmd["cldbid"].as<ClientDbId>();
if(!serverInstance->databaseHelper()->validClientDatabaseId(this->server, cldbid))
return command_result{error::client_invalid_id};
auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cldbid);
auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->getServerId(), 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));
ts::command::bulk_parser::PermissionBulksParser<false> pparser{cmd};
@ -1062,7 +1062,7 @@ command_result ConnectedClient::handleCommandClientPermList(Command &cmd) {
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_client_permission_list, 1);
if(!serverInstance->databaseHelper()->validClientDatabaseId(this->server, cmd["cldbid"])) return command_result{error::client_invalid_id};
auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cmd["cldbid"]);
auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->getServerId(), cmd["cldbid"]);
if (!this->notifyClientPermList(cmd["cldbid"], mgr, cmd.hasParm("permsid"))) return command_result{error::database_empty_result};
return command_result{error::ok};
}

View File

@ -443,9 +443,9 @@ command_result ConnectedClient::handleCommandSetClientChannelGroup(Command &cmd)
CMD_RESET_IDLE;
CMD_CHK_AND_INC_FLOOD_POINTS(25);
auto serverGroup = this->server->groups->findGroup(cmd["cgid"].as<GroupId>());
auto serverGroup = this->server->group_manager()->findGroup(cmd["cgid"].as<GroupId>());
if (!serverGroup && cmd["cgid"].as<GroupId>() == 0)
serverGroup = this->server->groups->defaultGroup(GroupTarget::GROUPTARGET_CHANNEL);
serverGroup = this->server->group_manager()->defaultGroup(GroupTarget::GROUPTARGET_CHANNEL);
if (!serverGroup || serverGroup->target() != GROUPTARGET_CHANNEL)
return command_result{error::group_invalid_id};
@ -481,7 +481,7 @@ command_result ConnectedClient::handleCommandSetClientChannelGroup(Command &cmd)
std::shared_ptr<GroupAssignment> old_group;
{
old_group = this->server->groups->getChannelGroupExact(target_cldbid, channel, false);
old_group = this->server->group_manager()->getChannelGroupExact(target_cldbid, channel, false);
if(old_group) {
auto channel_group_member_remove_power = this->calculate_permission(permission::i_channel_group_member_remove_power, channel_id);
if(!old_group->group->permission_granted(permission::i_channel_group_needed_member_remove_power, channel_group_member_remove_power, true)) {
@ -495,14 +495,14 @@ command_result ConnectedClient::handleCommandSetClientChannelGroup(Command &cmd)
}
}
this->server->groups->setChannelGroup(target_cldbid, serverGroup, channel);
this->server->group_manager()->setChannelGroup(target_cldbid, serverGroup, channel);
std::shared_ptr<ConnectedClient> connected_client{};
for (const auto &targetClient : this->server->findClientsByCldbId(target_cldbid)) {
connected_client = targetClient;
unique_lock client_channel_lock_w(targetClient->channel_lock);
auto updates = this->server->groups->update_server_group_property(targetClient, false, targetClient->getChannel()); /* needs a write lock */
auto updates = this->server->group_manager()->update_server_group_property(targetClient, false, targetClient->getChannel()); /* needs a write lock */
client_channel_lock_w.unlock();
shared_lock client_channel_lock_r(targetClient->channel_lock);
auto result = this->server->notifyClientPropertyUpdates(targetClient, updates);
@ -530,7 +530,7 @@ command_result ConnectedClient::handleCommandSetClientChannelGroup(Command &cmd)
target_cldbid, connected_client ? connected_client->getDisplayName() : ""
);
}
if(serverGroup != this->server->groups->defaultGroup(GroupTarget::GROUPTARGET_CHANNEL)) {
if(serverGroup != this->server->group_manager()->defaultGroup(GroupTarget::GROUPTARGET_CHANNEL)) {
serverInstance->action_logger()->group_assignment_logger.log_group_assignment_add(this->getServerId(),
this->ref(), log::GroupTarget::CHANNEL,
serverGroup->groupId(), serverGroup->name(),
@ -1241,7 +1241,7 @@ void check_token_action_permissions(const std::shared_ptr<ConnectedClient>& clie
switch(action.type) {
case ActionType::AddServerGroup: {
auto target_group = client->getServer()->getGroupManager()->findGroup(action.id1);
auto target_group = client->getServer()->group_manager()->findGroup(action.id1);
if(!target_group || target_group->type() == GroupType::GROUP_TYPE_TEMPLATE || target_group->target() != GroupTarget::GROUPTARGET_SERVER) {
action.type = ActionType::ActionIgnore;
result.set_result(index, ts::command_result{error::group_invalid_id});
@ -1258,7 +1258,7 @@ void check_token_action_permissions(const std::shared_ptr<ConnectedClient>& clie
}
case ActionType::RemoveServerGroup: {
auto target_group = client->getServer()->getGroupManager()->findGroup(action.id1);
auto target_group = client->getServer()->group_manager()->findGroup(action.id1);
if(!target_group || target_group->type() == GroupType::GROUP_TYPE_TEMPLATE || target_group->target() != GroupTarget::GROUPTARGET_SERVER) {
action.type = ActionType::ActionIgnore;
result.set_result(index, ts::command_result{error::group_invalid_id});
@ -1275,7 +1275,7 @@ void check_token_action_permissions(const std::shared_ptr<ConnectedClient>& clie
}
case ActionType::SetChannelGroup: {
auto target_group = client->getServer()->getGroupManager()->findGroup(action.id1);
auto target_group = client->getServer()->group_manager()->findGroup(action.id1);
if(!target_group || target_group->type() == GroupType::GROUP_TYPE_TEMPLATE || target_group->target() != GroupTarget::GROUPTARGET_CHANNEL) {
action.type = ActionType::ActionIgnore;
result.set_result(index, ts::command_result{error::group_invalid_id});
@ -2043,7 +2043,7 @@ command_result ConnectedClient::handleCommandPermFind(Command &cmd) {
perms.resize(entries.size());
size_t index{0};
auto all_groups = this->server->groups->availableGroups(true);
auto all_groups = this->server->group_manager()->availableGroups(true);
for(const auto& entry : entries) {
auto& perm = perms[index++];
@ -2183,9 +2183,9 @@ command_result ConnectedClient::handleCommandPermOverview(Command &cmd) {
auto channel = this->server ? this->server->channelTree->findChannel(cmd["cid"]) : serverInstance->getChannelTree()->findChannel(cmd["cid"]);
if(!channel) return command_result{error::channel_invalid_id};
auto server_groups = this->server->getGroupManager()->getServerGroups(client_dbid, ClientType::CLIENT_TEAMSPEAK);
auto channel_group = this->server->getGroupManager()->getChannelGroup(client_dbid, channel, true);
auto permission_manager = serverInstance->databaseHelper()->loadClientPermissionManager(this->getServer(), client_dbid);
auto server_groups = this->server->group_manager()->getServerGroups(client_dbid, ClientType::CLIENT_TEAMSPEAK);
auto channel_group = this->server->group_manager()->getChannelGroup(client_dbid, channel, true);
auto permission_manager = serverInstance->databaseHelper()->loadClientPermissionManager(this->getServerId(), client_dbid);
Command result(this->getExternalType() == ClientType::CLIENT_TEAMSPEAK ? "notifypermoverview" : "");
size_t index = 0;
@ -2796,11 +2796,11 @@ command_result ConnectedClient::handleCommandQueryList(ts::Command &cmd) {
auto global_list = permission::v2::permission_granted(1,
server ? server->calculate_permission(permission::b_client_query_list, this->getClientDatabaseId(), this->getType(), 0) :
serverInstance->calculate_permission(permission::b_client_query_list, this->getClientDatabaseId(), this->getType(), 0)
serverInstance->permission_helper().calculate_permission(permission::b_client_query_list, this->getClientDatabaseId(), this->getType(), 0)
);
auto own_list = global_list || permission::v2::permission_granted(1,
server ? server->calculate_permission(permission::b_client_query_list_own, this->getClientDatabaseId(), this->getType(), 0) :
serverInstance->calculate_permission(permission::b_client_query_list_own, this->getClientDatabaseId(), this->getType(), 0)
serverInstance->permission_helper().calculate_permission(permission::b_client_query_list_own, this->getClientDatabaseId(), this->getType(), 0)
);
if(!own_list && !global_list)
@ -2861,7 +2861,7 @@ command_result ConnectedClient::handleCommandQueryCreate(ts::Command &cmd) {
if(!permission::v2::permission_granted(1, server->calculate_permission(permission::b_client_query_create, this->getClientDatabaseId(), this->getType(), 0)))
return command_result{permission::b_client_query_create};
} else {
if(!permission::v2::permission_granted(1, serverInstance->calculate_permission(permission::b_client_query_create, this->getClientDatabaseId(), this->getType(), 0)))
if(!permission::v2::permission_granted(1, serverInstance->permission_helper().calculate_permission(permission::b_client_query_create, this->getClientDatabaseId(), this->getType(), 0)))
return command_result{permission::b_client_query_create};
}
@ -2874,7 +2874,7 @@ command_result ConnectedClient::handleCommandQueryCreate(ts::Command &cmd) {
if(!permission::v2::permission_granted(1, server->calculate_permission(permission::b_client_query_create_own, this->getClientDatabaseId(), this->getType(), 0)))
return command_result{permission::b_client_query_create_own};
} else {
if(!permission::v2::permission_granted(1, serverInstance->calculate_permission(permission::b_client_query_create_own, this->getClientDatabaseId(), this->getType(), 0)))
if(!permission::v2::permission_granted(1, serverInstance->permission_helper().calculate_permission(permission::b_client_query_create_own, this->getClientDatabaseId(), this->getType(), 0)))
return command_result{permission::b_client_query_create_own};
}
}
@ -2910,11 +2910,11 @@ command_result ConnectedClient::handleCommandQueryDelete(ts::Command &cmd) {
auto delete_all = permission::v2::permission_granted(1,
server ? server->calculate_permission(permission::b_client_query_delete, this->getClientDatabaseId(), this->getType(), 0) :
serverInstance->calculate_permission(permission::b_client_query_delete, this->getClientDatabaseId(), this->getType(), 0)
serverInstance->permission_helper().calculate_permission(permission::b_client_query_delete, this->getClientDatabaseId(), this->getType(), 0)
);
auto delete_own = delete_all || permission::v2::permission_granted(1,
server ? server->calculate_permission(permission::b_client_query_delete_own, this->getClientDatabaseId(), this->getType(), 0) :
serverInstance->calculate_permission(permission::b_client_query_delete_own, this->getClientDatabaseId(), this->getType(), 0)
serverInstance->permission_helper().calculate_permission(permission::b_client_query_delete_own, this->getClientDatabaseId(), this->getType(), 0)
);
if(account->unique_id == this->getUid()) {
@ -2946,11 +2946,11 @@ command_result ConnectedClient::handleCommandQueryRename(ts::Command &cmd) {
auto rename_all = permission::v2::permission_granted(1,
server ? server->calculate_permission(permission::b_client_query_rename, this->getClientDatabaseId(), this->getType(), 0) :
serverInstance->calculate_permission(permission::b_client_query_rename, this->getClientDatabaseId(), this->getType(), 0)
serverInstance->permission_helper().calculate_permission(permission::b_client_query_rename, this->getClientDatabaseId(), this->getType(), 0)
);
auto rename_own = rename_all || permission::v2::permission_granted(1,
server ? server->calculate_permission(permission::b_client_query_rename_own, this->getClientDatabaseId(), this->getType(), 0) :
serverInstance->calculate_permission(permission::b_client_query_rename_own, this->getClientDatabaseId(), this->getType(), 0)
serverInstance->permission_helper().calculate_permission(permission::b_client_query_rename_own, this->getClientDatabaseId(), this->getType(), 0)
);
if(account->unique_id == this->getUid()) {
@ -2985,11 +2985,11 @@ command_result ConnectedClient::handleCommandQueryChangePassword(ts::Command &cm
auto change_all = permission::v2::permission_granted(1,
server ? server->calculate_permission(permission::b_client_query_change_password, this->getClientDatabaseId(), this->getType(), 0) :
serverInstance->calculate_permission(permission::b_client_query_change_password_global, this->getClientDatabaseId(), this->getType(), 0)
serverInstance->permission_helper().calculate_permission(permission::b_client_query_change_password_global, this->getClientDatabaseId(), this->getType(), 0)
);
auto change_own = change_all || permission::v2::permission_granted(1,
server ? server->calculate_permission(permission::b_client_query_change_own_password, this->getClientDatabaseId(), this->getType(), 0) :
serverInstance->calculate_permission(permission::b_client_query_change_own_password, this->getClientDatabaseId(), this->getType(), 0)
serverInstance->permission_helper().calculate_permission(permission::b_client_query_change_own_password, this->getClientDatabaseId(), this->getType(), 0)
);
auto password = cmd[0].has("client_login_password") ? cmd["client_login_password"].as<string>() : "";

View File

@ -87,22 +87,22 @@ command_result ConnectedClient::handleCommandServerEdit(Command &cmd) {
SERVEREDIT_CHK_PROP_CACHED("virtualserver_codec_encryption_mode", permission::b_virtualserver_modify_codec_encryption_mode, int) }
SERVEREDIT_CHK_PROP_CACHED("virtualserver_default_server_group", permission::b_virtualserver_modify_default_servergroup, GroupId)
if(target_server) {
auto group = target_server->groups->findGroup(cmd["virtualserver_default_server_group"].as<GroupId>());
auto group = target_server->group_manager()->findGroup(cmd["virtualserver_default_server_group"].as<GroupId>());
if (!group || group->target() != GROUPTARGET_SERVER) return command_result{error::parameter_invalid};
}
} SERVEREDIT_CHK_PROP_CACHED("virtualserver_default_channel_group", permission::b_virtualserver_modify_default_channelgroup, GroupId)
if(target_server) {
auto group = target_server->groups->findGroup(cmd["virtualserver_default_channel_group"].as<GroupId>());
auto group = target_server->group_manager()->findGroup(cmd["virtualserver_default_channel_group"].as<GroupId>());
if (!group || group->target() != GROUPTARGET_CHANNEL) return command_result{error::parameter_invalid};
}
} SERVEREDIT_CHK_PROP_CACHED("virtualserver_default_channel_admin_group", permission::b_virtualserver_modify_default_channeladmingroup, GroupId)
if(target_server) {
auto group = target_server->groups->findGroup(cmd["virtualserver_default_channel_admin_group"].as<GroupId>());
auto group = target_server->group_manager()->findGroup(cmd["virtualserver_default_channel_admin_group"].as<GroupId>());
if (!group || group->target() != GROUPTARGET_CHANNEL) return command_result{error::parameter_invalid};
}
} SERVEREDIT_CHK_PROP_CACHED("virtualserver_default_music_group", permission::b_virtualserver_modify_default_musicgroup, GroupId)
if(target_server) {
auto group = target_server->groups->findGroup(cmd["virtualserver_default_music_group"].as<GroupId>());
auto group = target_server->group_manager()->findGroup(cmd["virtualserver_default_music_group"].as<GroupId>());
if (!group || group->target() != GROUPTARGET_SERVER) return command_result{error::parameter_invalid};
}
}
@ -226,7 +226,7 @@ command_result ConnectedClient::handleCommandServerEdit(Command &cmd) {
if(target_server) {
if (group_update)
target_server->forEachClient([&](const shared_ptr<ConnectedClient>& client) {
if(target_server->notifyClientPropertyUpdates(client, target_server->groups->update_server_group_property(client, true, client->getChannel()))) {
if(target_server->notifyClientPropertyUpdates(client, target_server->group_manager()->update_server_group_property(client, true, client->getChannel()))) {
client->task_update_needed_permissions.enqueue();
}
});
@ -314,7 +314,7 @@ command_result ConnectedClient::handleCommandServerGroupAdd(Command &cmd) {
log_group_type = log::GroupType::NORMAL;
}
auto group_manager = this->server ? this->server->getGroupManager() : serverInstance->getOldGroupManager().get();
auto group_manager = this->server ? this->server->group_manager() : serverInstance->group_manager().get();
for(const auto& gr : group_manager->availableServerGroups(true)) {
if(gr->name() == cmd["name"].string() && gr->target() == GroupTarget::GROUPTARGET_SERVER) {
return command_result{error::parameter_invalid, "Group already exists"};
@ -360,7 +360,7 @@ command_result ConnectedClient::handleCommandServerGroupCopy(Command &cmd) {
auto ref_server = this->server;
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_servergroup_create, 1);
auto group_manager = this->server ? this->server->groups : serverInstance->getOldGroupManager().get();
auto group_manager = this->server ? this->server->group_manager() : serverInstance->group_manager().get();
auto source_group_id = cmd["ssgid"].as<GroupId>();
auto source_group = group_manager->findGroup(source_group_id);
@ -494,7 +494,7 @@ command_result ConnectedClient::handleCommandServerGroupRename(Command &cmd) {
CMD_RESET_IDLE;
CMD_CHK_AND_INC_FLOOD_POINTS(5);
auto group_manager = this->server ? this->server->getGroupManager() : serverInstance->getOldGroupManager().get();
auto group_manager = this->server ? this->server->group_manager() : serverInstance->group_manager().get();
auto serverGroup = group_manager->findGroup(cmd["sgid"].as<GroupId>());
if (!serverGroup || serverGroup->target() != GROUPTARGET_SERVER) return command_result{error::group_invalid_id};
@ -529,7 +529,7 @@ command_result ConnectedClient::handleCommandServerGroupDel(Command &cmd) {
CMD_CHK_AND_INC_FLOOD_POINTS(5);
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_servergroup_delete, 1);
auto group_manager = this->server ? this->server->getGroupManager() : serverInstance->getOldGroupManager().get();
auto group_manager = this->server ? this->server->group_manager() : serverInstance->group_manager().get();
auto serverGroup = group_manager->findGroup(cmd["sgid"].as<GroupId>());
if (!serverGroup || serverGroup->target() != GROUPTARGET_SERVER) return command_result{error::group_invalid_id};
ACTION_REQUIRES_GROUP_PERMISSION(serverGroup, permission::i_server_group_needed_modify_power, permission::i_server_group_modify_power, true);
@ -566,7 +566,7 @@ command_result ConnectedClient::handleCommandServerGroupDel(Command &cmd) {
serverInstance->action_logger()->group_logger.log_group_delete(this->getServerId(), this->ref(), log::GroupTarget::SERVER, log_group_type, serverGroup->groupId(), serverGroup->name());
if(this->server)
this->server->forEachClient([&](shared_ptr<ConnectedClient> cl) {
if(this->server->notifyClientPropertyUpdates(cl, this->server->groups->update_server_group_property(cl, true, cl->getChannel()))) {
if(this->server->notifyClientPropertyUpdates(cl, this->server->group_manager()->update_server_group_property(cl, true, cl->getChannel()))) {
cl->task_update_needed_permissions.enqueue();
}
cl->notifyServerGroupList();
@ -589,7 +589,7 @@ command_result ConnectedClient::handleCommandServerGroupClientList(Command &cmd)
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_servergroup_client_list, 1);
auto server = cmd[0].has("sid") && cmd["sid"] == 0 ? nullptr : this->server;
auto groupManager = server ? this->server->groups : serverInstance->getOldGroupManager().get();
auto groupManager = server ? this->server->group_manager() : serverInstance->group_manager().get();
auto serverGroup = groupManager->findGroup(cmd["sgid"].as<GroupId>());
if (!serverGroup || serverGroup->target() != GROUPTARGET_SERVER) return command_result{error::group_invalid_id};
@ -617,7 +617,7 @@ command_result ConnectedClient::handleCommandServerGroupAddClient(Command &cmd)
CMD_CHK_AND_INC_FLOOD_POINTS(25);
auto target_server = cmd[0].has("sid") && cmd["sid"] == 0 ? nullptr : this->server;
auto group_manager = target_server ? this->server->groups : serverInstance->getOldGroupManager().get();
auto group_manager = target_server ? this->server->group_manager() : serverInstance->group_manager().get();
auto target_cldbid = cmd["cldbid"].as<ClientDbId>();
if (!serverInstance->databaseHelper()->validClientDatabaseId(target_server, cmd["cldbid"])) return command_result{error::client_invalid_id, "invalid cldbid"};
@ -714,7 +714,7 @@ command_result ConnectedClient::handleCommandServerGroupAddClient(Command &cmd)
for(const auto& _server : target_server ? std::deque<shared_ptr<VirtualServer>>{target_server} : serverInstance->getVoiceServerManager()->serverInstances()) {
for (const auto &targetClient : _server->findClientsByCldbId(target_cldbid)) {
connected_client = targetClient;
if (_server->notifyClientPropertyUpdates(targetClient, _server->groups->update_server_group_property(targetClient, true, targetClient->getChannel()))) {
if (_server->notifyClientPropertyUpdates(targetClient, _server->group_manager()->update_server_group_property(targetClient, true, targetClient->getChannel()))) {
for (const auto &client : _server->getClients()) {
if(client->isClientVisible(targetClient, true) || client == targetClient)
for(const auto& group : applied_groups)
@ -741,7 +741,7 @@ command_result ConnectedClient::handleCommandServerGroupDelClient(Command &cmd)
CMD_CHK_AND_INC_FLOOD_POINTS(25);
auto target_server = cmd[0].has("sid") && cmd["sid"] == 0 ? nullptr : this->server;
auto group_manager = target_server ? this->server->groups : serverInstance->getOldGroupManager().get();
auto group_manager = target_server ? this->server->group_manager() : serverInstance->group_manager().get();
auto target_cldbid = cmd["cldbid"].as<ClientDbId>();
if (!serverInstance->databaseHelper()->validClientDatabaseId(target_server, cmd["cldbid"])) return command_result{error::client_invalid_id, "invalid cldbid"};
@ -852,7 +852,7 @@ command_result ConnectedClient::handleCommandServerGroupDelClient(Command &cmd)
ConnectedLockedClient clock{targetClient};
if(!clock) continue;
if (_server->notifyClientPropertyUpdates(targetClient, _server->groups->update_server_group_property(targetClient, true, targetClient->getChannel()))) {
if (_server->notifyClientPropertyUpdates(targetClient, _server->group_manager()->update_server_group_property(targetClient, true, targetClient->getChannel()))) {
for (const auto &client : _server->getClients()) {
if(client->isClientVisible(targetClient, true) || client == targetClient)
for(const auto& group : applied_groups)
@ -879,7 +879,7 @@ command_result ConnectedClient::handleCommandServerGroupPermList(Command &cmd) {
CMD_CHK_AND_INC_FLOOD_POINTS(5);
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_servergroup_permission_list, 1);
auto serverGroup = (this->server ? this->server->groups : serverInstance->getOldGroupManager().get())->findGroup(cmd["sgid"].as<GroupId>());
auto serverGroup = (this->server ? this->server->group_manager() : serverInstance->group_manager().get())->findGroup(cmd["sgid"].as<GroupId>());
if (!serverGroup) return command_result{error::group_invalid_id};
if(this->getType() == ClientType::CLIENT_TEAMSPEAK && this->command_times.last_notify + this->command_times.notify_timeout < system_clock::now()) {
@ -894,7 +894,7 @@ command_result ConnectedClient::handleCommandServerGroupAddPerm(Command &cmd) {
CMD_RESET_IDLE;
CMD_CHK_AND_INC_FLOOD_POINTS(5);
auto serverGroup = (this->server ? this->server->groups : serverInstance->getOldGroupManager().get())->findGroup(cmd["sgid"].as<GroupId>());
auto serverGroup = (this->server ? this->server->group_manager() : serverInstance->group_manager().get())->findGroup(cmd["sgid"].as<GroupId>());
if (!serverGroup) return command_result{error::group_invalid_id};
if (serverGroup->target() != GROUPTARGET_SERVER) return command_result{error::parameter_invalid};
ACTION_REQUIRES_GROUP_PERMISSION(serverGroup, permission::i_server_group_needed_modify_power, permission::i_server_group_modify_power, 1);
@ -959,7 +959,7 @@ command_result ConnectedClient::handleCommandServerGroupDelPerm(Command &cmd) {
CMD_RESET_IDLE;
CMD_CHK_AND_INC_FLOOD_POINTS(5);
auto serverGroup = (this->server ? this->server->groups : serverInstance->getOldGroupManager().get())->findGroup(cmd["sgid"].as<GroupId>());
auto serverGroup = (this->server ? this->server->group_manager() : serverInstance->group_manager().get())->findGroup(cmd["sgid"].as<GroupId>());
if (!serverGroup) return command_result{error::group_invalid_id};
if (serverGroup->target() != GROUPTARGET_SERVER) return command_result{error::parameter_invalid};
ACTION_REQUIRES_GROUP_PERMISSION(serverGroup, permission::i_server_group_needed_modify_power, permission::i_server_group_modify_power, 1);
@ -1024,7 +1024,7 @@ command_result ConnectedClient::handleCommandServerGroupAutoAddPerm(ts::Command&
CMD_CHK_AND_INC_FLOOD_POINTS(25);
auto ref_server = this->server;
auto group_manager = ref_server ? this->server->groups : &*serverInstance->getOldGroupManager();
auto group_manager = ref_server ? this->server->group_manager() : &*serverInstance->group_manager();
deque<shared_ptr<Group>> groups;
for(const auto& group : group_manager->availableGroups(false)) {
@ -1102,7 +1102,7 @@ command_result ConnectedClient::handleCommandServerGroupAutoDelPerm(ts::Command&
CMD_CHK_AND_INC_FLOOD_POINTS(25);
auto ref_server = this->server;
auto group_manager = ref_server ? this->server->groups : &*serverInstance->getOldGroupManager();
auto group_manager = ref_server ? this->server->group_manager() : &*serverInstance->group_manager();
deque<shared_ptr<Group>> groups;
for(const auto& group : group_manager->availableGroups(false)) {
@ -1184,14 +1184,14 @@ command_result ConnectedClient::handleCommandServerGroupsByClientId(Command &cmd
int index = 0;
if (this->server) {
for (const auto &group : this->server->groups->getAssignedServerGroups(cldbid)) {
for (const auto &group : this->server->group_manager()->getAssignedServerGroups(cldbid)) {
result[index]["name"] = group->group->name();
result[index]["sgid"] = group->group->groupId();
result[index]["cldbid"] = cldbid;
index++;
}
} else {
for (const auto &group : serverInstance->getOldGroupManager()->getAssignedServerGroups(cldbid)) {
for (const auto &group : serverInstance->group_manager()->getAssignedServerGroups(cldbid)) {
result[index]["name"] = group->group->name();
result[index]["sgid"] = group->group->groupId();
result[index]["cldbid"] = cldbid;

View File

@ -631,9 +631,9 @@ void QueryClient::disconnect_from_virtual_server(const std::string& reason) {
this->currentChannel = nullptr;
}
old_server->groups->disableCache(this->getClientDatabaseId());
old_server->group_manager()->disableCache(this->getClientDatabaseId());
this->loadDataForCurrentServer();
}
serverInstance->getOldGroupManager()->enableCache(this->getClientDatabaseId());
serverInstance->group_manager()->enableCache(this->getClientDatabaseId());
}

View File

@ -247,8 +247,8 @@ command_result QueryClient::handleCommandLogin(Command& cmd) {
this->server->client_move(this->ref(), nullptr, nullptr, "", ViewReasonId::VREASON_USER_ACTION, false, tree_lock);
this->server->unregisterClient(this->ref(), "login", tree_lock);
}
this->server->groups->disableCache(this->getClientDatabaseId());
} else serverInstance->getOldGroupManager()->disableCache(this->getClientDatabaseId());
this->server->group_manager()->disableCache(this->getClientDatabaseId());
} else serverInstance->group_manager()->disableCache(this->getClientDatabaseId());
logMessage(LOG_QUERY, "Got new authenticated client. Username: {}, Unique-ID: {}, Bounded Server: {}", account->username, account->unique_id, account->bound_server);
@ -268,7 +268,7 @@ command_result QueryClient::handleCommandLogin(Command& cmd) {
DatabaseHelper::assignDatabaseId(this->sql, static_cast<ServerId>(target_server ? target_server->getServerId() : 0), this->ref());
if(target_server) {
target_server->groups->enableCache(this->getClientDatabaseId());
target_server->group_manager()->enableCache(this->getClientDatabaseId());
target_server->registerClient(this->ref());
{
@ -292,7 +292,7 @@ command_result QueryClient::handleCommandLogin(Command& cmd) {
this->task_update_needed_permissions.enqueue();
}
} else {
serverInstance->getOldGroupManager()->enableCache(this->getClientDatabaseId());
serverInstance->group_manager()->enableCache(this->getClientDatabaseId());
this->task_update_needed_permissions.enqueue();
}
@ -317,15 +317,15 @@ command_result QueryClient::handleCommandLogout(Command &) {
this->server->client_move(this->ref(), nullptr, nullptr, "", ViewReasonId::VREASON_USER_ACTION, false, tree_lock);
this->server->unregisterClient(this->ref(), "logout", tree_lock);
}
this->server->groups->disableCache(this->getClientDatabaseId());
} else serverInstance->getOldGroupManager()->disableCache(this->getClientDatabaseId());
this->server->group_manager()->disableCache(this->getClientDatabaseId());
} else serverInstance->group_manager()->disableCache(this->getClientDatabaseId());
this->properties()[property::CLIENT_UNIQUE_IDENTIFIER] = "UnknownQuery"; //TODO load from table
this->properties()[property::CLIENT_NICKNAME] = string() + "ServerQuery#" + this->getLoggingPeerIp() + "/" + to_string(ntohs(this->getPeerPort()));
DatabaseHelper::assignDatabaseId(this->sql, static_cast<ServerId>(this->server ? this->server->getServerId() : 0), this->ref());
if(this->server){
this->server->groups->enableCache(this->getClientDatabaseId());
this->server->group_manager()->enableCache(this->getClientDatabaseId());
this->server->registerClient(this->ref());
{
@ -346,7 +346,7 @@ command_result QueryClient::handleCommandLogout(Command &) {
this->task_update_needed_permissions.enqueue();
}
} else {
serverInstance->getOldGroupManager()->enableCache(this->getClientDatabaseId());
serverInstance->group_manager()->enableCache(this->getClientDatabaseId());
this->task_update_needed_permissions.enqueue();
}
@ -400,7 +400,7 @@ command_result QueryClient::handleCommandServerSelect(Command &cmd) {
DatabaseHelper::assignDatabaseId(this->sql, static_cast<ServerId>(this->server ? this->server->getServerId() : 0), this->ref());
if(this->server) {
this->server->groups->enableCache(this->getClientDatabaseId());
this->server->group_manager()->enableCache(this->getClientDatabaseId());
this->server->registerClient(this->ref());
{
@ -419,7 +419,7 @@ command_result QueryClient::handleCommandServerSelect(Command &cmd) {
this->task_update_needed_permissions.enqueue();
}
} else {
serverInstance->getOldGroupManager()->enableCache(this->getClientDatabaseId());
serverInstance->group_manager()->enableCache(this->getClientDatabaseId());
this->task_update_needed_permissions.enqueue();
}

View File

@ -227,7 +227,7 @@ bool WebClient::close_connection(const std::chrono::system_clock::time_point& ti
unique_lock server_channel_lock(this->server->channel_tree_lock);
this->server->unregisterClient(this->ref(), "disconnected", server_channel_lock);
}
this->server->groups->disableCache(this->getClientDatabaseId());
this->server->group_manager()->disableCache(this->getClientDatabaseId());
//this->server = nullptr;
}

View File

@ -61,6 +61,36 @@ namespace ts::server::groups {
return value.has_value ? value.value : 0;
}
[[nodiscard]] inline bool is_permanent() {
auto permission_manager = this->permissions_;
assert(permission_manager);
const auto data = permission_manager->permission_value_flagged(permission::b_group_is_permanent);
return data.has_value ? data.value == 1 : false;
}
[[nodiscard]] inline permission::PermissionValue update_type() {
auto permission_manager = this->permissions_;
assert(permission_manager);
const auto data = permission_manager->permission_value_flagged(permission::i_group_auto_update_type);
return data.has_value ? data.value : 0;
}
[[nodiscard]] inline bool permission_granted(const permission::PermissionType& permission, const permission::v2::PermissionFlaggedValue& granted_value, bool require_granted_value) {
auto permission_manager = this->permissions_;;
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;
}
private:
const ServerId virtual_server_id_;
const GroupId group_id_;

View File

@ -217,7 +217,7 @@ std::vector<ts::GroupId> GroupAssignmentManager::server_groups_of_client(ts::ser
return result;
}
std::vector<ChannelGroupAssignment> GroupAssignmentManager::channel_group_of_client(GroupAssignmentCalculateMode mode, ClientDbId cldbid) {
std::vector<ChannelGroupAssignment> GroupAssignmentManager::channel_groups_of_client(GroupAssignmentCalculateMode mode, ClientDbId cldbid) {
std::vector<ChannelGroupAssignment> result{};
bool cache_found{false};
{
@ -262,7 +262,7 @@ std::vector<ChannelGroupAssignment> GroupAssignmentManager::channel_group_of_cli
if(mode == GroupAssignmentCalculateMode::GLOBAL) {
if(auto parent = this->manager_->parent_manager(); parent) {
auto parent_groups = parent->assignments().channel_group_of_client(mode, cldbid);
auto parent_groups = parent->assignments().channel_groups_of_client(mode, cldbid);
result.reserve(result.size() + parent_groups.size());
result.insert(result.begin(), parent_groups.begin(), parent_groups.end());
}
@ -271,6 +271,21 @@ std::vector<ChannelGroupAssignment> GroupAssignmentManager::channel_group_of_cli
return result;
}
std::optional<ChannelGroupAssignment> GroupAssignmentManager::channel_group_of_client(GroupAssignmentCalculateMode mode,
ClientDbId client_database_id, ChannelId channel_id) {
/* TODO: Improve performance by not querying all groups */
auto assignments = this->channel_groups_of_client(mode, client_database_id);
for(const auto& assignment : assignments) {
if(assignment.channel_id != channel_id) {
continue;
}
return std::make_optional(assignment);
}
return std::nullopt;
}
std::deque<ts::ClientDbId> GroupAssignmentManager::server_group_clients(GroupId group_id) {
std::deque<ts::ClientDbId> result{};
if constexpr(kCacheAllClients) {
@ -279,8 +294,9 @@ std::deque<ts::ClientDbId> GroupAssignmentManager::server_group_clients(GroupId
auto it = std::find_if(client->server_group_assignments.begin(), client->server_group_assignments.end(), [&](const ServerGroupAssignment& assignment) {
return assignment.group_id == group_id;
});
if(it == client->server_group_assignments.end())
if(it == client->server_group_assignments.end()) {
continue;
}
result.push_back(client->client_database_id);
}
} else {
@ -436,8 +452,10 @@ GroupAssignmentResult GroupAssignmentManager::set_channel_group(ClientDbId clien
}
}
}
if(temporary)
if(temporary) {
return GroupAssignmentResult::SUCCESS;
}
sql::command(this->sql_manager(), "DELETE FROM `assignedGroups` WHERE `serverId` = :sid AND `cldbid` = :cldbid AND `channelId` = :chid",
variable{":sid", this->server_id()},

View File

@ -69,7 +69,8 @@ namespace ts::server {
/* info/query methods */
[[nodiscard]] std::vector<GroupId> server_groups_of_client(GroupAssignmentCalculateMode /* mode */, ClientDbId /* client database id */);
[[nodiscard]] std::vector<ChannelGroupAssignment> channel_group_of_client(GroupAssignmentCalculateMode /* mode */, ClientDbId /* client database id */);
[[nodiscard]] std::vector<ChannelGroupAssignment> channel_groups_of_client(GroupAssignmentCalculateMode /* mode */, ClientDbId /* client database id */);
[[nodiscard]] std::optional<ChannelGroupAssignment> channel_group_of_client(GroupAssignmentCalculateMode /* mode */, ClientDbId /* client database id */, ChannelId /* channel id */);
[[nodiscard]] std::deque<ClientDbId> server_group_clients(GroupId /* group id */);
//[[nodiscard]] std::deque<ClientDbId> channel_group_clients(GroupId /* group id */, ChannelId /* channel id */);

View File

@ -38,6 +38,26 @@ bool GroupManager::initialize(const std::shared_ptr<GroupManager>& self, std::st
return true;
}
void GroupManager::save_permissions() {
size_t total_groups_server, total_groups_channel;
size_t saved_groups_server, saved_groups_channel;
auto timestamp_0 = std::chrono::system_clock::now();
this->server_groups_->save_permissions(total_groups_server, saved_groups_server);
auto timestamp_1 = std::chrono::system_clock::now();
this->channel_groups_->save_permissions(total_groups_channel, saved_groups_channel);
auto timestamp_2 = std::chrono::system_clock::now();
auto time_server_groups = std::chrono::duration_cast<std::chrono::milliseconds>(timestamp_1 - timestamp_0).count();
auto time_channel_groups = std::chrono::duration_cast<std::chrono::milliseconds>(timestamp_2 - timestamp_1).count();
debugMessage(this->server_id(), "Saved {}/{} server and {}/{} channel group permissions in {}ms or {}ms",
saved_groups_server, total_groups_server,
saved_groups_channel, total_groups_channel,
time_server_groups, time_channel_groups
);
}
/* Abstract group manager */
AbstractGroupManager::AbstractGroupManager(
sql::SqlManager* database,
@ -149,6 +169,19 @@ int AbstractGroupManager::insert_group_from_sql(int length, std::string *values,
return 0;
}
void AbstractGroupManager::save_permissions() {
std::unique_lock group_lock{this->groups_};
auto groups = this->groups_;
group_lock.unlock();
for(auto& group : groups) {
auto permissions = group->permissions();
if(permissions->require_db_updates()) {
serverInstance->databaseHelper()->saveGroupPermissions(0, group->group_id(), (uint8_t) this->database_target_, permissions);
}
}
}
std::shared_ptr<Group> AbstractGroupManager::find_group_(GroupCalculateMode mode, GroupId group_id) {
{
std::lock_guard glock{this->group_mutex_};

View File

@ -74,6 +74,8 @@ namespace ts::server::groups {
GroupLoadResult load_data(bool /* initialize */ = false);
void unload_data();
void reset_groups(bool /* cleanup database */);
void save_permissions(size_t& /* total groups */, size_t& /* saved groups */);
protected:
std::shared_ptr<AbstractGroupManager> parent_manager_;
DatabaseGroupTarget database_target_;
@ -113,6 +115,25 @@ namespace ts::server::groups {
public:
ServerGroupManager(const std::shared_ptr<GroupManager>& /* owner */, std::shared_ptr<ServerGroupManager> /* parent */);
[[nodiscard]] inline std::vector<std::shared_ptr<ServerGroup>> available_groups(GroupCalculateMode mode) {
std::vector<std::shared_ptr<ServerGroup>> result{};
if(auto manager{std::dynamic_pointer_cast<ServerGroupManager>(this->parent_manager_)}; manager && mode != GroupCalculateMode::LOCAL) {
auto result_ = manager->available_groups(mode);
result.reserve(result_.size());
result.insert(result.end(), result_.begin(), result_.end());
}
{
std::lock_guard group_lock{this->group_mutex_};
result.reserve(this->groups_.size());
for(const auto& group : this->groups_) {
result.push_back(this->cast_result(group));
}
}
return result;
}
[[nodiscard]] inline std::shared_ptr<ServerGroup> find_group(GroupCalculateMode mode, GroupId group_id) {
return this->cast_result(this->find_group_(mode, group_id));
}
@ -166,6 +187,25 @@ namespace ts::server::groups {
public:
ChannelGroupManager(const std::shared_ptr<GroupManager>& /* owner */, std::shared_ptr<ChannelGroupManager> /* parent */);
[[nodiscard]] inline std::vector<std::shared_ptr<ChannelGroup>> available_groups(GroupCalculateMode mode) {
std::vector<std::shared_ptr<ChannelGroup>> result{};
if(auto manager{std::dynamic_pointer_cast<ChannelGroupManager>(this->parent_manager_)}; manager && mode != GroupCalculateMode::LOCAL) {
auto result_ = manager->available_groups(mode);
result.reserve(result_.size());
result.insert(result.end(), result_.begin(), result_.end());
}
{
std::lock_guard group_lock{this->group_mutex_};
result.reserve(this->groups_.size());
for(const auto& group : this->groups_) {
result.push_back(this->cast_result(group));
}
}
return result;
}
[[nodiscard]] inline std::shared_ptr<ChannelGroup> find_group(GroupCalculateMode mode, GroupId group_id) {
return this->cast_result(this->find_group_(mode, group_id));
}
@ -226,6 +266,7 @@ namespace ts::server::groups {
bool initialize(const std::shared_ptr<GroupManager>& /* self ref, */, std::string& /* error */);
[[nodiscard]] inline const std::shared_ptr<GroupManager>& parent_manager() { return this->parent_manager_; }
void save_permissions();
[[nodiscard]] inline GroupAssignmentManager& assignments() { return this->assignment_manager_; }
[[nodiscard]] inline const std::shared_ptr<ServerGroupManager>& server_groups() { return this->server_groups_; }

View File

@ -96,7 +96,7 @@ std::shared_ptr<server::MusicClient> MusicBotManager::createBot(ClientDbId owner
if(!config::music::enabled) return nullptr;
handle->groups->enableCache(musicBot->getClientDatabaseId());
handle->group_manager()->enableCache(musicBot->getClientDatabaseId());
handle->registerClient(musicBot);
{
@ -147,7 +147,7 @@ void MusicBotManager::deleteBot(std::shared_ptr<server::MusicClient> musicBot) {
handle->client_move(musicBot, nullptr, nullptr, "Music bot deleted", ViewReasonId::VREASON_SERVER_LEFT, true, server_channel_lock);
handle->unregisterClient(musicBot, "bot deleted", server_channel_lock);
}
handle->groups->disableCache(musicBot->getClientDatabaseId());
handle->group_manager()->disableCache(musicBot->getClientDatabaseId());
serverInstance->databaseHelper()->deleteClient(handle, musicBot->getClientDatabaseId());
serverInstance->databaseHelper()->deleteClient(nullptr, musicBot->getClientDatabaseId());
@ -241,7 +241,7 @@ int MusicBotManager::sqlCreateMusicBot(int length, std::string* values, std::str
musicBot->properties()[property::CLIENT_LASTCONNECTED] = duration_cast<seconds>(system_clock::now().time_since_epoch()).count();
}
handle->groups->enableCache(musicBot->getClientDatabaseId());
handle->group_manager()->enableCache(musicBot->getClientDatabaseId());
if(musicBot->getClientDatabaseId() != botId) logCritical(handle->getServerId(),"Invalid music bot id mapping!");
{

View File

@ -42,9 +42,9 @@ void QueryServer::unregisterConnection(const shared_ptr<QueryClient> &client) {
}
if(client->server) {
client->server->getGroupManager()->disableCache(client->getClientDatabaseId());
client->server->group_manager()->disableCache(client->getClientDatabaseId());
} else {
serverInstance->getOldGroupManager()->disableCache(client->getClientDatabaseId());
serverInstance->group_manager()->disableCache(client->getClientDatabaseId());
}
/* client->handle = nullptr; */
}

View File

@ -293,7 +293,7 @@ namespace terminal::chandler {
return false;
}
auto group = server->getGroupManager()->findGroup(groupId);
auto group = server->group_manager()->findGroup(groupId);
if(!group) {
handle.response.emplace_back("Could not resolve server group!");
return false;

2
shared

@ -1 +1 @@
Subproject commit 799bf8d26b5742e3e5df3c9ecbca233113d8f73d
Subproject commit b26132fa5498a1966bb11bbf9d1ee6bb32f39863