Fixed some subscribe issues
This commit is contained in:
		
							parent
							
								
									b3347cfa8e
								
							
						
					
					
						commit
						46753d7a3f
					
				@ -1 +1 @@
 | 
				
			|||||||
Subproject commit d2b3e9bcadea5130b8ae906d9a1e656351f59936
 | 
					Subproject commit ac79fda3b2d409e2fa023a5f38c380121cd7ee93
 | 
				
			||||||
@ -622,19 +622,19 @@ void DatabaseHelper::saveChannelPermissions(const std::shared_ptr<ts::server::TS
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void DatabaseHelper::assign_default_properties_client(Properties *properties, ClientType type){
 | 
					std::shared_ptr<Properties> DatabaseHelper::default_properties_client(std::shared_ptr<Properties> properties, ClientType type){
 | 
				
			||||||
    Properties& _properties = *properties;
 | 
						if(!properties)
 | 
				
			||||||
 | 
							properties = make_shared<Properties>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_properties.register_property_type<property::ClientProperties>();
 | 
						properties->register_property_type<property::ClientProperties>();
 | 
				
			||||||
	_properties.register_property_type<property::ConnectionProperties>();
 | 
						properties->register_property_type<property::ConnectionProperties>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(type == ClientType::CLIENT_MUSIC){
 | 
						if(type == ClientType::CLIENT_MUSIC || type == ClientType::CLIENT_QUERY){
 | 
				
			||||||
		_properties[property::CLIENT_INPUT_HARDWARE] = true;
 | 
							(*properties)[property::CLIENT_INPUT_HARDWARE] = true;
 | 
				
			||||||
		_properties[property::CLIENT_OUTPUT_HARDWARE] = true;
 | 
							(*properties)[property::CLIENT_OUTPUT_HARDWARE] = true;
 | 
				
			||||||
	} else if(type == ClientType::CLIENT_QUERY) {
 | 
					 | 
				
			||||||
		_properties[property::CLIENT_INPUT_HARDWARE] = true;
 | 
					 | 
				
			||||||
		_properties[property::CLIENT_OUTPUT_HARDWARE] = true;
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return properties;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool DatabaseHelper::assignDatabaseId(sql::SqlManager *sql, ServerId id, std::shared_ptr<DataClient> cl) {
 | 
					bool DatabaseHelper::assignDatabaseId(sql::SqlManager *sql, ServerId id, std::shared_ptr<DataClient> cl) {
 | 
				
			||||||
@ -954,8 +954,7 @@ std::shared_ptr<Properties> DatabaseHelper::loadChannelProperties(const shared_p
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::shared_ptr<Properties> DatabaseHelper::loadClientProperties(const std::shared_ptr<TSServer>& server, ClientDbId cldbid, ClientType type) {
 | 
					std::shared_ptr<Properties> DatabaseHelper::loadClientProperties(const std::shared_ptr<TSServer>& server, ClientDbId cldbid, ClientType type) {
 | 
				
			||||||
    auto props = std::make_shared<Properties>();
 | 
					    auto props = DatabaseHelper::default_properties_client(nullptr, type);
 | 
				
			||||||
    assign_default_properties_client(props.get(), type);
 | 
					 | 
				
			||||||
    if(server) {
 | 
					    if(server) {
 | 
				
			||||||
        props->operator[](property::CLIENT_DESCRIPTION) = server->properties()[property::VIRTUALSERVER_DEFAULT_CLIENT_DESCRIPTION].value();
 | 
					        props->operator[](property::CLIENT_DESCRIPTION) = server->properties()[property::VIRTUALSERVER_DEFAULT_CLIENT_DESCRIPTION].value();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -76,7 +76,7 @@ namespace ts {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        class DatabaseHelper {
 | 
					        class DatabaseHelper {
 | 
				
			||||||
            public:
 | 
					            public:
 | 
				
			||||||
                static void assign_default_properties_client(Properties *, ClientType type);
 | 
					                static std::shared_ptr<Properties> default_properties_client(std::shared_ptr<Properties> /* properties */, ClientType /* type */);
 | 
				
			||||||
                static bool assignDatabaseId(sql::SqlManager *, ServerId id, std::shared_ptr<DataClient>);
 | 
					                static bool assignDatabaseId(sql::SqlManager *, ServerId id, std::shared_ptr<DataClient>);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                explicit DatabaseHelper(sql::SqlManager*);
 | 
					                explicit DatabaseHelper(sql::SqlManager*);
 | 
				
			||||||
 | 
				
			|||||||
@ -523,8 +523,20 @@ void TSServer::client_move(
 | 
				
			|||||||
			if(!deleted.empty())
 | 
								if(!deleted.empty())
 | 
				
			||||||
				target->notifyChannelHide(deleted, false);
 | 
									target->notifyChannelHide(deleted, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if(!s_source_channel->permission_granted(permission::i_channel_needed_subscribe_power, target->calculate_permission_value(permission::i_channel_subscribe_power, s_source_channel->channelId()), false))
 | 
								auto i_source_channel = s_source_channel->channelId();
 | 
				
			||||||
				target->unsubscribeChannel({s_source_channel}, false); //Unsubscribe last channel (hasn't permissions)
 | 
								if(std::find(deleted.begin(), deleted.end(), i_source_channel) == deleted.end()) {
 | 
				
			||||||
 | 
									auto source_channel_sub_power = target->calculate_permission_value(permission::i_channel_subscribe_power, i_source_channel);
 | 
				
			||||||
 | 
									if(!s_source_channel->permission_granted(permission::i_channel_needed_subscribe_power, source_channel_sub_power, false)) {
 | 
				
			||||||
 | 
										auto source_channel_sub_power_ignore = target->calculate_permission_value(permission::b_channel_ignore_subscribe_power, i_source_channel);
 | 
				
			||||||
 | 
										if(!DataClient::permission_granted(source_channel_sub_power_ignore, 1, true)) {
 | 
				
			||||||
 | 
											logTrace(this->serverId, "Force unsubscribing of client {} for channel {}/{}. (Channel switch and no permissions)",
 | 
				
			||||||
 | 
											         CLIENT_STR_LOG_PREFIX_(target), s_source_channel->name(),
 | 
				
			||||||
 | 
											         i_source_channel
 | 
				
			||||||
 | 
											);
 | 
				
			||||||
 | 
											target->unsubscribeChannel({s_source_channel}, false); //Unsubscribe last channel (hasn't permissions)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			TIMING_STEP(timings, "src hide ts");
 | 
								TIMING_STEP(timings, "src hide ts");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -246,9 +246,10 @@ std::deque<std::shared_ptr<BasicChannel>> ConnectedClient::subscribeChannel(cons
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			if(!general_granted && channel != this->currentChannel) {
 | 
								if(!general_granted && channel != this->currentChannel) {
 | 
				
			||||||
				auto granted_permission = this->calculate_permission_value(permission::i_channel_subscribe_power, channel->channelId());
 | 
									auto granted_permission = this->calculate_permission_value(permission::i_channel_subscribe_power, channel->channelId());
 | 
				
			||||||
				if((granted_permission.has_value && granted_permission.value == -1) || !channel->permission_granted(permission::i_channel_needed_subscribe_power, granted_permission, false)) {
 | 
					
 | 
				
			||||||
 | 
									if(!channel->permission_granted(permission::i_channel_needed_subscribe_power, granted_permission, false)) {
 | 
				
			||||||
					auto ignore_power = this->calculate_permission_value(permission::b_channel_ignore_subscribe_power, channel->channelId());
 | 
										auto ignore_power = this->calculate_permission_value(permission::b_channel_ignore_subscribe_power, channel->channelId());
 | 
				
			||||||
					if(!ignore_power.has_value && ignore_power.value < 1)
 | 
										if(!ignore_power.has_value || ignore_power.value < 1)
 | 
				
			||||||
						continue;
 | 
											continue;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
				
			|||||||
@ -5646,7 +5646,7 @@ CommandResult ConnectedClient::handleCommandMessageList(Command &cmd) {
 | 
				
			|||||||
    CMD_CHK_AND_INC_FLOOD_POINTS(5);
 | 
					    CMD_CHK_AND_INC_FLOOD_POINTS(5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto msgList = this->server->letters->avariableLetters(this->getUid());
 | 
					    auto msgList = this->server->letters->avariableLetters(this->getUid());
 | 
				
			||||||
    if (msgList.empty()) return {findError("database_empty_result"), "no letters avaraible"};
 | 
					    if (msgList.empty()) return {findError("database_empty_result"), "no letters available"};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Command notify(this->getExternalType() == CLIENT_TEAMSPEAK ? "notifymessagelist" : "");
 | 
					    Command notify(this->getExternalType() == CLIENT_TEAMSPEAK ? "notifymessagelist" : "");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -13,12 +13,9 @@ using namespace ts;
 | 
				
			|||||||
using namespace ts::server;
 | 
					using namespace ts::server;
 | 
				
			||||||
using namespace ts::permission;
 | 
					using namespace ts::permission;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern ts::server::InstanceHandler* serverInstance;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
DataClient::DataClient(sql::SqlManager* database, const std::shared_ptr<TSServer>& server) : server(server), sql(database) {
 | 
					DataClient::DataClient(sql::SqlManager* database, const std::shared_ptr<TSServer>& server) : server(server), sql(database) {
 | 
				
			||||||
    assert(database);
 | 
					    assert(database);
 | 
				
			||||||
    this->_properties = std::make_shared<Properties>();
 | 
					    this->_properties = DatabaseHelper::default_properties_client(nullptr, ClientType::CLIENT_INTERNAL);
 | 
				
			||||||
    DatabaseHelper::assign_default_properties_client(this->_properties.get(), ClientType::CLIENT_INTERNAL);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DataClient::~DataClient() {
 | 
					DataClient::~DataClient() {
 | 
				
			||||||
@ -28,26 +25,48 @@ DataClient::~DataClient() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
bool DataClient::loadDataForCurrentServer() { //TODO for query
 | 
					bool DataClient::loadDataForCurrentServer() { //TODO for query
 | 
				
			||||||
    if(this->getUid().empty()) return false;
 | 
					    if(this->getUid().empty()) return false;
 | 
				
			||||||
 | 
					    auto ref_server = this->server;
 | 
				
			||||||
 | 
					    auto server_id = ref_server ? ref_server->getServerId() : 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    properties()[property::CLIENT_DATABASE_ID] = 0;
 | 
					    properties()[property::CLIENT_DATABASE_ID] = 0;
 | 
				
			||||||
    properties()[property::CLIENT_CREATED] = 0;
 | 
					    properties()[property::CLIENT_CREATED] = 0;
 | 
				
			||||||
    properties()[property::CLIENT_TOTALCONNECTIONS] = 0;
 | 
					    properties()[property::CLIENT_TOTALCONNECTIONS] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sql::command(this->sql, "SELECT `cldbid`,`firstConnect`,`connections` FROM `clients` WHERE `serverId` = :sid AND `clientUid`=:uid LIMIT 1", variable{":sid", this->server ? this->server->getServerId() : 0}, variable{":uid", this->getUid()}).query([&](DataClient* cl, int length, string* values, string* names){
 | 
					    ClientDbId client_db_id = 0;
 | 
				
			||||||
        for (int index = 0; index < length; index++) {
 | 
					    sql::command(this->sql, "SELECT `cldbid`,`firstConnect`,`connections` FROM `clients` WHERE `serverId` = :sid AND `clientUid` = :uid LIMIT 1",
 | 
				
			||||||
            logTrace(this->server ? this->server->getServerId() : 0, "Reading client (" + this->getUid() + ") property from client database table. (Key: " + names[index] + ", Value: " + values[index] + ")");
 | 
					    		variable{":sid", server_id},
 | 
				
			||||||
            if (names[index] == "cldbid") {
 | 
					    		variable{":uid", this->getUid()}
 | 
				
			||||||
                cl->properties()[property::CLIENT_DATABASE_ID] = string(values[index]);
 | 
					    ).query([&](DataClient* cl, int length, string* values, string* names){
 | 
				
			||||||
            } else if (names[index] == "firstConnect") {
 | 
						    for (int index = 0; index < length; index++) {
 | 
				
			||||||
                cl->properties()[property::CLIENT_CREATED] = values[index];
 | 
						        try {
 | 
				
			||||||
            } else if (names[index] == "connections") {
 | 
								    if (names[index] == "cldbid") {
 | 
				
			||||||
                cl->properties()[property::CLIENT_TOTALCONNECTIONS] = values[index];
 | 
									    client_db_id = stoull(values[index]);
 | 
				
			||||||
            } else {
 | 
								    } else if (names[index] == "firstConnect") {
 | 
				
			||||||
                debugMessage(lstream << "Unknown row name '" << names[index] << "'" << endl);
 | 
									    cl->properties()[property::CLIENT_CREATED] = values[index];
 | 
				
			||||||
            }
 | 
								    } else if (names[index] == "connections") {
 | 
				
			||||||
        }
 | 
									    cl->properties()[property::CLIENT_TOTALCONNECTIONS] = values[index];
 | 
				
			||||||
 | 
								    } else {
 | 
				
			||||||
 | 
									    logWarning(LOG_INSTANCE, "Received unknown column with name {} within client list", names[index]);
 | 
				
			||||||
 | 
								    }
 | 
				
			||||||
 | 
							    } catch(const std::exception& ex) {
 | 
				
			||||||
 | 
							        logError(server_id, "Failed to load client {} base properties from database. Colum parsing for column {} failed. Value: {}. Message: {}",
 | 
				
			||||||
 | 
					                   this->getUid(),
 | 
				
			||||||
 | 
					                   names[index],
 | 
				
			||||||
 | 
					                   values[index],
 | 
				
			||||||
 | 
					                   ex.what()
 | 
				
			||||||
 | 
						            );
 | 
				
			||||||
 | 
							        return 0;
 | 
				
			||||||
 | 
							    }
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
    }, this);
 | 
					    }, this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(client_db_id == 0)
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						this->properties()[property::CLIENT_DATABASE_ID] = client_db_id; /* do this before the property saving (it saved the cldbid as well!)*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//Load general properties
 | 
						//Load general properties
 | 
				
			||||||
	deque<ts::PropertyWrapper> copied;
 | 
						deque<ts::PropertyWrapper> copied;
 | 
				
			||||||
	for(const auto& prop : this->_properties->list_properties()){
 | 
						for(const auto& prop : this->_properties->list_properties()){
 | 
				
			||||||
@ -56,20 +75,19 @@ bool DataClient::loadDataForCurrentServer() { //TODO for query
 | 
				
			|||||||
		copied.push_back(prop);
 | 
							copied.push_back(prop);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(this->getClientDatabaseId() == 0) return false;
 | 
					    if(!ref_server) {
 | 
				
			||||||
    if(!this->server) {
 | 
					 | 
				
			||||||
        if(this->getType() == ClientType::CLIENT_WEB || this->getType() == ClientType::CLIENT_TEAMSPEAK)
 | 
					        if(this->getType() == ClientType::CLIENT_WEB || this->getType() == ClientType::CLIENT_TEAMSPEAK)
 | 
				
			||||||
            logCritical("Got a voice or web manager, which is unbound to any server!");
 | 
					            logCritical(LOG_INSTANCE, "Got a voice or web client, which is unbound to any server!");
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    auto clType = this->getType();
 | 
					    auto client_type = this->getType();
 | 
				
			||||||
    if(this->getType() == CLIENT_TEAMSPEAK || this->server) {
 | 
					    if(client_type == CLIENT_TEAMSPEAK || ref_server) {
 | 
				
			||||||
        this->_properties = serverInstance->databaseHelper()->loadClientProperties(this->server, this->getClientDatabaseId(), clType);
 | 
					        this->_properties = serverInstance->databaseHelper()->loadClientProperties(ref_server, this->getClientDatabaseId(), client_type);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        this->_properties = std::make_shared<Properties>();
 | 
					        this->_properties = DatabaseHelper::default_properties_client(nullptr, client_type);
 | 
				
			||||||
        DatabaseHelper::assign_default_properties_client(this->_properties.get(), clType);
 | 
					
 | 
				
			||||||
        this->_properties->registerNotifyHandler([&](Property& prop){
 | 
					        this->_properties->registerNotifyHandler([&, server_id, client_db_id](Property& prop){
 | 
				
			||||||
            std::string query;
 | 
					            std::string query;
 | 
				
			||||||
            if(prop.type() == property::CLIENT_TOTALCONNECTIONS)
 | 
					            if(prop.type() == property::CLIENT_TOTALCONNECTIONS)
 | 
				
			||||||
                query = "UPDATE `clients` SET `connections` = :value WHERE `serverId` = :sid AND `cldbid` = :cldbid";
 | 
					                query = "UPDATE `clients` SET `connections` = :value WHERE `serverId` = :sid AND `cldbid` = :cldbid";
 | 
				
			||||||
@ -77,9 +95,12 @@ bool DataClient::loadDataForCurrentServer() { //TODO for query
 | 
				
			|||||||
                query = "UPDATE `clients` SET `lastName` = :value WHERE `serverId` = :sid AND `cldbid` = :cldbid";
 | 
					                query = "UPDATE `clients` SET `lastName` = :value WHERE `serverId` = :sid AND `cldbid` = :cldbid";
 | 
				
			||||||
            else if(prop.type() == property::CLIENT_LASTCONNECTED)
 | 
					            else if(prop.type() == property::CLIENT_LASTCONNECTED)
 | 
				
			||||||
                query = "UPDATE `clients` SET `lastConnect` = :value WHERE `serverId` = :sid AND `cldbid` = :cldbid";
 | 
					                query = "UPDATE `clients` SET `lastConnect` = :value WHERE `serverId` = :sid AND `cldbid` = :cldbid";
 | 
				
			||||||
            if(query.empty()) return;
 | 
					            else
 | 
				
			||||||
            debugMessage("[SQL] " + query + " - " + to_string(0) + " - " + prop.value() + " - " + to_string(this->getClientDatabaseId()));
 | 
					            	return;
 | 
				
			||||||
            sql::command(this->sql, query, variable{":sid", 0}, variable{":cldbid", this->getClientDatabaseId()}, variable{":value", prop.value()}).executeLater().waitAndGetLater(LOG_SQL_CMD, {1, "future failed"});
 | 
					
 | 
				
			||||||
 | 
					            debugMessage(server_id, "[Property] Updating general client table property for client {}. Key: {} Value: {}", client_db_id, prop.type().name, prop.value());
 | 
				
			||||||
 | 
					            sql::command(this->sql, query, variable{":sid", 0}, variable{":cldbid", client_db_id}, variable{":value", prop.value()}).executeLater()
 | 
				
			||||||
 | 
					            .waitAndGetLater(LOG_SQL_CMD, {1, "failed to update general client properties"});
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -91,35 +112,21 @@ bool DataClient::loadDataForCurrentServer() { //TODO for query
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    this->_properties->toggleSave(true);
 | 
					    this->_properties->toggleSave(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /*
 | 
						this->clientPermissions = serverInstance->databaseHelper()->loadClientPermissionManager(ref_server, this->getClientDatabaseId());
 | 
				
			||||||
     * //TODO What did this?
 | 
					 | 
				
			||||||
    vector<string> updatedProps;
 | 
					 | 
				
			||||||
    if(this->server) {
 | 
					 | 
				
			||||||
        auto cclient = dynamic_cast<ConnectedClient*>(this);
 | 
					 | 
				
			||||||
        if(cclient){
 | 
					 | 
				
			||||||
            if(cclient->state == CONNECTED)
 | 
					 | 
				
			||||||
                this->server->notifyClientPropertyUpdates(dynamic_cast<ConnectedClient*>(this)->_this.lock(), updatedProps);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
	this->clientPermissions = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, this->getClientDatabaseId());
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //Setup / fix stuff
 | 
					    //Setup / fix stuff
 | 
				
			||||||
    if(!this->properties()[property::CLIENT_FLAG_AVATAR].as<string>().empty()){
 | 
					    if(!this->properties()[property::CLIENT_FLAG_AVATAR].as<string>().empty()){
 | 
				
			||||||
        if(
 | 
					        if(
 | 
				
			||||||
                !this->server ||
 | 
					                !ref_server ||
 | 
				
			||||||
                !serverInstance->getFileServer()->findFile("/avatar_" + this->getAvatarId(),serverInstance->getFileServer()->avatarDirectory(this->server))) {
 | 
					                !serverInstance->getFileServer()->findFile("/avatar_" + this->getAvatarId(),serverInstance->getFileServer()->avatarDirectory(ref_server))) {
 | 
				
			||||||
        	if(config::server::delete_missing_icon_permissions)
 | 
					        	if(config::server::delete_missing_icon_permissions)
 | 
				
			||||||
                this->properties()[property::CLIENT_FLAG_AVATAR] = "";
 | 
					                this->properties()[property::CLIENT_FLAG_AVATAR] = "";
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(this->server){
 | 
					    if(ref_server)
 | 
				
			||||||
        int ureadMessages = 0;
 | 
						    this->properties()[property::CLIENT_UNREAD_MESSAGES] = ref_server->letters->unread_letter_count(this->getUid());
 | 
				
			||||||
        for(const auto &elm : this->server->letters->avariableLetters(this->getUid()))
 | 
					
 | 
				
			||||||
            if(!elm->read) ureadMessages++;
 | 
					 | 
				
			||||||
        this->properties()[property::CLIENT_UNREAD_MESSAGES] = ureadMessages;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -90,24 +90,29 @@ namespace ts {
 | 
				
			|||||||
                virtual permission::PermissionValue getPermissionGrantValue(permission::PermissionTestType test, permission::PermissionType, const std::shared_ptr<BasicChannel>& targetChannel = nullptr);
 | 
					                virtual permission::PermissionValue getPermissionGrantValue(permission::PermissionTestType test, permission::PermissionType, const std::shared_ptr<BasicChannel>& targetChannel = nullptr);
 | 
				
			||||||
                virtual bool permissionGrantGranted(permission::PermissionTestType test, permission::PermissionType, permission::PermissionValue, const std::shared_ptr<BasicChannel>& targetChannel = nullptr, bool required = true);
 | 
					                virtual bool permissionGrantGranted(permission::PermissionTestType test, permission::PermissionType, permission::PermissionValue, const std::shared_ptr<BasicChannel>& targetChannel = nullptr, bool required = true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                inline bool permission_granted(permission::PermissionType, permission::PermissionValue, bool = false) = delete; /* we dont accept permission type enums! */
 | 
					                template <typename T>
 | 
				
			||||||
                inline bool permission_granted(ts::permission::PermissionValue value, ts::permission::PermissionValue required, bool enforce_required = true) {
 | 
					                inline bool permission_granted(T, permission::PermissionValue, bool = false) = delete; /* only permission values */
 | 
				
			||||||
                    if(required == permNotGranted || required == 0) {
 | 
					                [[deprecated]] __always_inline bool permission_granted(ts::permission::PermissionValue value, ts::permission::PermissionValue required, bool enforce_required = true) {
 | 
				
			||||||
                        if(enforce_required)
 | 
					                    return DataClient::permission_granted({value, value != permNotGranted}, required, enforce_required);
 | 
				
			||||||
                            return value == -1 || value > 0;
 | 
					 | 
				
			||||||
                        else
 | 
					 | 
				
			||||||
                            return true;
 | 
					 | 
				
			||||||
                    } else if(value == permNotGranted) {
 | 
					 | 
				
			||||||
                        return false;
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        if(value == -1)
 | 
					 | 
				
			||||||
                            return true;
 | 
					 | 
				
			||||||
                        else if(value >= required)
 | 
					 | 
				
			||||||
                            return true;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                    return false;
 | 
					 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							        static inline bool permission_granted(ts::permission::v2::PermissionFlaggedValue value, ts::permission::PermissionValue required, bool enforce_required = true) {
 | 
				
			||||||
 | 
								        if(required == permNotGranted || required == 0) {
 | 
				
			||||||
 | 
									        if(enforce_required)
 | 
				
			||||||
 | 
										        return value.value == -1 || value.value > 0;
 | 
				
			||||||
 | 
									        else
 | 
				
			||||||
 | 
										        return true;
 | 
				
			||||||
 | 
								        } else if(!value.has_value) {
 | 
				
			||||||
 | 
									        return false;
 | 
				
			||||||
 | 
								        } else {
 | 
				
			||||||
 | 
									        if(value.value == -1)
 | 
				
			||||||
 | 
										        return true;
 | 
				
			||||||
 | 
									        else if(value.value >= required)
 | 
				
			||||||
 | 
										        return true;
 | 
				
			||||||
 | 
								        }
 | 
				
			||||||
 | 
								        return false;
 | 
				
			||||||
 | 
							        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                virtual std::vector<std::shared_ptr<GroupAssignment>> assignedServerGroups();
 | 
					                virtual std::vector<std::shared_ptr<GroupAssignment>> assignedServerGroups();
 | 
				
			||||||
                virtual std::shared_ptr<GroupAssignment> assignedChannelGroup(const std::shared_ptr<BasicChannel> &);
 | 
					                virtual std::shared_ptr<GroupAssignment> assignedChannelGroup(const std::shared_ptr<BasicChannel> &);
 | 
				
			||||||
                virtual bool serverGroupAssigned(const std::shared_ptr<Group> &);
 | 
					                virtual bool serverGroupAssigned(const std::shared_ptr<Group> &);
 | 
				
			||||||
 | 
				
			|||||||
@ -14,6 +14,28 @@ using namespace ts::server;
 | 
				
			|||||||
LetterManager::LetterManager(server::TSServer* server) : server(server) {}
 | 
					LetterManager::LetterManager(server::TSServer* server) : server(server) {}
 | 
				
			||||||
LetterManager::~LetterManager() {}
 | 
					LetterManager::~LetterManager() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					size_t LetterManager::unread_letter_count(const ts::ClientUid &client_unique_id) {
 | 
				
			||||||
 | 
						size_t result = 0;
 | 
				
			||||||
 | 
						auto res = sql::command(this->server->getSql(), "SELECT COUNT(*) FROM `letters` WHERE `serverId` = :sid AND `receiver` = :uid AND `read` = :false",
 | 
				
			||||||
 | 
								variable{":sid", this->server ? this->server->getServerId() : 0},
 | 
				
			||||||
 | 
								variable{":uid", client_unique_id},
 | 
				
			||||||
 | 
								variable{":false", 0}
 | 
				
			||||||
 | 
						).query([&](int length, std::string* values, std::string* columns) {
 | 
				
			||||||
 | 
							if(length != 1)
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							try {
 | 
				
			||||||
 | 
								result = stoll(values[0]);
 | 
				
			||||||
 | 
							} catch(std::exception& ex) {
 | 
				
			||||||
 | 
								logError(this->server ? this->server->getServerId() : 0, "Failed to parse unread letter count: {}", ex.what());
 | 
				
			||||||
 | 
								return 1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
						(LOG_SQL_CMD)(res);
 | 
				
			||||||
 | 
						return result;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::vector<std::shared_ptr<LetterHeader>> LetterManager::avariableLetters(ClientUid cluid) {
 | 
					std::vector<std::shared_ptr<LetterHeader>> LetterManager::avariableLetters(ClientUid cluid) {
 | 
				
			||||||
    vector<shared_ptr<LetterHeader>> result;
 | 
					    vector<shared_ptr<LetterHeader>> result;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -30,6 +30,7 @@ namespace ts {
 | 
				
			|||||||
                ~LetterManager();
 | 
					                ~LetterManager();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                size_t unread_letter_count(const ClientUid&);
 | 
				
			||||||
                std::vector<std::shared_ptr<LetterHeader>> avariableLetters(ClientUid);
 | 
					                std::vector<std::shared_ptr<LetterHeader>> avariableLetters(ClientUid);
 | 
				
			||||||
                std::shared_ptr<Letter> getFullLetter(LetterId);
 | 
					                std::shared_ptr<Letter> getFullLetter(LetterId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								shared
									
									
									
									
									
								
							
							
								
								
								
								
								
								
									
									
								
							
						
						
									
										2
									
								
								shared
									
									
									
									
									
								
							@ -1 +1 @@
 | 
				
			|||||||
Subproject commit 3b3574d54df493a8a767e2c691c8769468b758dc
 | 
					Subproject commit 60ed95fb63463e71d423d555f316f071900d8fb6
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user