Teaspeak-Server/server/src/Group.h

235 lines
10 KiB
C++

#pragma once
#include <list>
#include <chrono>
#include <BasicChannel.h>
#include <ThreadPool/Mutex.h>
#include "PermissionManager.h"
#include "Properties.h"
#include "channel/ServerChannel.h"
#include "Definitions.h"
#include "Properties.h"
#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,
GROUP_TYPE_QUERY //Only aplies for servergroups
};
enum GroupTarget {
GROUPTARGET_SERVER,
GROUPTARGET_CHANNEL
};
enum GroupNameMode {
GROUP_NAMEMODE_HIDDEN,
GROUP_NAMEMODE_BEFORE,
GROUP_NAMEMODE_BEHIND
};
}
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::vector<std::shared_ptr<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::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);
};
}