#pragma once #include #include #include #include #include "PermissionManager.h" #include "Properties.h" #include "channel/ServerChannel.h" #include "Definitions.h" #include "Properties.h" #include 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 until; }; struct GroupAssignment { GroupAssignment() {} GroupAssignment(CachedClient *parent, ServerId server, uint64_t channelId, const std::shared_ptr &group, const std::chrono::time_point &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; std::chrono::time_point until; inline bool isPermanent(){ return std::chrono::time_point_cast(until).time_since_epoch().count() == 0; } }; struct CachedClient { ClientDbId client_database_id; std::vector> server_groups; std::map> 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 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& manager); GroupManager* handle; std::shared_ptr _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 &, sql::SqlManager *, std::shared_ptr root = nullptr); ~GroupManager(); bool loadGroupFormDatabase(GroupId id = 0); std::vector> availableGroups(bool root = true); std::vector> availableServerGroups(bool root = true); std::vector> availableChannelGroups(bool root = true); std::vector> getAssignedServerGroups(ClientDbId cldbid); inline bool hasServerGroupAssigned(uint64_t cldbId, const std::shared_ptr& group){ for(const auto& assign : this->getAssignedServerGroups(cldbId)) if(assign->group == group) return true; return false; } std::shared_ptr get_group_assignment(const ClientDbId& client_database_id, const std::shared_ptr& group) { for(const auto& assign : this->getAssignedServerGroups(client_database_id)) if(assign->group == group) return assign; return nullptr; } std::vector> getServerGroups(ClientDbId cldbid, server::ClientType type); inline bool hasServerGroup(uint64_t cldbId, server::ClientType type, const std::shared_ptr& 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 getChannelGroup(ClientDbId cldbId, const std::shared_ptr &, bool assign_default); //Gets the channel group within the channel std::shared_ptr getChannelGroupExact(ClientDbId cldbId, const std::shared_ptr&, bool assign_default); std::vector> defaultServerGroupGroupAssignments(ClientDbId, server::ClientType); std::shared_ptr defaultChannelGroupAssignment(ClientDbId cldbId, const std::shared_ptr &); void addServerGroup(ClientDbId cldbId, std::shared_ptr, std::chrono::time_point until = std::chrono::time_point()); void removeServerGroup(ClientDbId cldbId, std::shared_ptr); void setChannelGroup(ClientDbId cldbId, std::shared_ptr, std::shared_ptr , std::chrono::time_point until = std::chrono::time_point()); std::shared_ptr createGroup(GroupTarget target, GroupType type, std::string name); GroupId copyGroup(std::shared_ptr group, GroupType type, std::string name, ServerId targetServerId); bool copyGroupPermissions(const std::shared_ptr& source, const std::shared_ptr& target); bool reloadGroupPermissions(std::shared_ptr); bool renameGroup(std::shared_ptr, std::string); bool deleteGroup(std::shared_ptr); bool deleteAllGroups(); std::vector> listGroupMembers(std::shared_ptr, bool names = false); std::vector> listGroupAssignments(ClientDbId client); void cleanupAssignments(ClientDbId); std::shared_ptr findGroup(GroupId); std::shared_ptr findGroupLocal(GroupId); std::vector> findGroup(GroupTarget target, std::string); std::shared_ptr defaultGroup(GroupTarget type, bool enforce_property = false); std::deque update_server_group_property(const std::shared_ptr &client, bool channel_lock, const std::shared_ptr& 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); protected: void handleChannelDeleted(const ChannelId& /* channel id */); private: std::shared_ptr root = nullptr; std::weak_ptr server; ServerId getServerId(); sql::SqlManager* sql; std::vector> groups; threads::Mutex cacheLock; std::vector> cachedClients; int insertGroupFromDb(int count, char** values, char** column); inline std::shared_ptr resolve_cached_client(ClientDbId client_database_id); }; }