2019-07-17 13:37:18 -04:00
|
|
|
#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 TSServer;
|
|
|
|
class ConnectedClient;
|
|
|
|
}
|
|
|
|
|
2019-09-14 08:22:16 -04:00
|
|
|
struct CachedClient;
|
2019-07-17 13:37:18 -04:00
|
|
|
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 {
|
2019-09-14 08:22:16 -04:00
|
|
|
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! */
|
2019-07-17 13:37:18 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
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::TSServer;
|
|
|
|
public:
|
|
|
|
static int64_t generateGroupId(sql::SqlManager* sql);
|
|
|
|
|
|
|
|
GroupManager(const std::shared_ptr<server::TSServer> &, 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;
|
|
|
|
}
|
|
|
|
|
2019-09-14 08:22:16 -04:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-07-17 13:37:18 -04:00
|
|
|
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);
|
2019-10-21 14:46:17 -04:00
|
|
|
GroupId copyGroup(std::shared_ptr<Group> group, GroupType type, std::string name, ServerId targetServerId);
|
2019-07-17 13:37:18 -04:00
|
|
|
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);
|
|
|
|
|
2019-10-29 11:06:34 -04:00
|
|
|
std::deque<property::ClientProperties> update_server_group_property(const std::shared_ptr<server::ConnectedClient> &client, bool channel_lock, const std::shared_ptr<BasicChannel>& channel);
|
2019-09-14 08:22:16 -04:00
|
|
|
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 */);
|
2019-07-17 13:37:18 -04:00
|
|
|
void clearCache();
|
|
|
|
|
|
|
|
|
|
|
|
bool isLocalGroup(std::shared_ptr<Group>);
|
|
|
|
protected:
|
2019-09-14 08:22:16 -04:00
|
|
|
void handleChannelDeleted(const ChannelId& /* channel id */);
|
2019-07-17 13:37:18 -04:00
|
|
|
private:
|
|
|
|
std::shared_ptr<GroupManager> root = nullptr;
|
|
|
|
std::weak_ptr<server::TSServer> 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);
|
|
|
|
|
2019-09-14 08:22:16 -04:00
|
|
|
inline std::shared_ptr<CachedClient> resolve_cached_client(ClientDbId client_database_id);
|
2019-07-17 13:37:18 -04:00
|
|
|
};
|
|
|
|
}
|