Using new permissions system consequently
This commit is contained in:
parent
bb2e7699dc
commit
c7b6c0a3ba
@ -3,7 +3,7 @@ project(TeaSpeak-Server)
|
|||||||
|
|
||||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||||
#--allow-multiple-definition
|
#--allow-multiple-definition
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive -Wall -Wno-reorder -Wno-sign-compare -static-libgcc -static-libstdc++ -g -Wl,--no-whole-archive -pthread ${MEMORY_DEBUG_FLAGS}")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fpermissive -Wall -Wno-reorder -Wno-sign-compare -static-libgcc -static-libstdc++ -g -Wl,--no-whole-archive -pthread ${MEMORY_DEBUG_FLAGS} -Werror=return-type")
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3")
|
||||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3")
|
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -O3")
|
||||||
|
|
||||||
@ -55,7 +55,12 @@ set(SERVER_SOURCE_FILES
|
|||||||
src/server/VoiceServer.cpp
|
src/server/VoiceServer.cpp
|
||||||
src/server/POWHandler.cpp
|
src/server/POWHandler.cpp
|
||||||
src/client/voice/VoiceClientConnection.cpp
|
src/client/voice/VoiceClientConnection.cpp
|
||||||
src/client/ConnectedClientCommandHandler.cpp
|
#src/client/ConnectedClientCommandHandler.cpp
|
||||||
|
src/client/command_handler/channel.cpp
|
||||||
|
src/client/command_handler/client.cpp
|
||||||
|
src/client/command_handler/server.cpp
|
||||||
|
src/client/command_handler/misc.cpp
|
||||||
|
|
||||||
src/client/ConnectedClientNotifyHandler.cpp
|
src/client/ConnectedClientNotifyHandler.cpp
|
||||||
src/ServerManager.cpp
|
src/ServerManager.cpp
|
||||||
src/server/file/FileServer.cpp
|
src/server/file/FileServer.cpp
|
||||||
@ -133,7 +138,7 @@ set(SERVER_SOURCE_FILES
|
|||||||
|
|
||||||
src/manager/ConversationManager.cpp
|
src/manager/ConversationManager.cpp
|
||||||
src/client/SpeakingClientHandshake.cpp
|
src/client/SpeakingClientHandshake.cpp
|
||||||
)
|
src/client/command_handler/music.cpp src/client/command_handler/file.cpp)
|
||||||
if (COMPILE_WEB_CLIENT)
|
if (COMPILE_WEB_CLIENT)
|
||||||
add_definitions(-DCOMPILE_WEB_CLIENT)
|
add_definitions(-DCOMPILE_WEB_CLIENT)
|
||||||
|
|
||||||
@ -146,7 +151,7 @@ if (COMPILE_WEB_CLIENT)
|
|||||||
src/client/web/WSWebClient.cpp
|
src/client/web/WSWebClient.cpp
|
||||||
src/client/web/SampleHandler.cpp
|
src/client/web/SampleHandler.cpp
|
||||||
src/client/web/VoiceBridge.cpp
|
src/client/web/VoiceBridge.cpp
|
||||||
)
|
src/client/command_handler/helpers.h)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
add_executable(PermHelper helpers/permgen.cpp)
|
add_executable(PermHelper helpers/permgen.cpp)
|
||||||
|
@ -881,4 +881,37 @@ void InstanceHandler::loadWebCertificate() {
|
|||||||
|
|
||||||
this->sslMgr->rename_context(strobf("web_default_new").string(), strobf("web_default").string());
|
this->sslMgr->rename_context(strobf("web_default_new").string(), strobf("web_default").string());
|
||||||
this->web_cert_revision = revision;
|
this->web_cert_revision = revision;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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{};
|
||||||
|
|
||||||
|
//TODO: Negate?
|
||||||
|
//TODO: May move this part to the instance?
|
||||||
|
|
||||||
|
auto server_groups = this->getGroupManager()->getServerGroups(cldbid, type);
|
||||||
|
for(const auto& permission : permissions) {
|
||||||
|
permission::v2::PermissionFlaggedValue value{0, false};
|
||||||
|
|
||||||
|
for(const auto &gr : this->getGroupManager()->getServerGroups(cldbid, type)){
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.emplace_back(permission, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
@ -72,6 +72,24 @@ namespace ts {
|
|||||||
|
|
||||||
std::shared_ptr<permission::PermissionNameMapper> getPermissionMapper() { return this->permission_mapper; }
|
std::shared_ptr<permission::PermissionNameMapper> getPermissionMapper() { return this->permission_mapper; }
|
||||||
std::shared_ptr<ts::event::EventExecutor> getConversationIo() { return this->conversation_io; }
|
std::shared_ptr<ts::event::EventExecutor> getConversationIo() { return this->conversation_io; }
|
||||||
|
|
||||||
|
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
|
||||||
|
);
|
||||||
private:
|
private:
|
||||||
std::mutex activeLock;
|
std::mutex activeLock;
|
||||||
std::condition_variable activeCon;
|
std::condition_variable activeCon;
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
#include "InstanceHandler.h"
|
#include "InstanceHandler.h"
|
||||||
#include "InstanceHandler.h"
|
#include "InstanceHandler.h"
|
||||||
|
|
||||||
|
//TODO: When using the new command builder make sure you're using a std::deque as the underlying bulk type!
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace ts;
|
using namespace ts;
|
||||||
using namespace ts::server;
|
using namespace ts::server;
|
||||||
|
@ -182,10 +182,10 @@ bool TSServer::assignDefaultChannel(const shared_ptr<ConnectedClient>& client, b
|
|||||||
else
|
else
|
||||||
channel = this->channelTree->findChannelByPath(str);
|
channel = this->channelTree->findChannelByPath(str);
|
||||||
if (channel) {
|
if (channel) {
|
||||||
if(!channel->permission_granted(permission::i_channel_needed_join_power, client->calculate_permission_value(permission::i_channel_join_power, channel->channelId()), false)) {
|
if(!channel->permission_granted(permission::i_channel_needed_join_power, client->calculate_permission(permission::i_channel_join_power, channel->channelId()), false)) {
|
||||||
logMessage(this->serverId, "{} Client tried to connect to a channel which he hasn't permission for. Channel: {} ({})", CLIENT_STR_LOG_PREFIX_(client), channel->channelId(), channel->name());
|
logMessage(this->serverId, "{} Client tried to connect to a channel which he hasn't permission for. Channel: {} ({})", CLIENT_STR_LOG_PREFIX_(client), channel->channelId(), channel->name());
|
||||||
channel = nullptr;
|
channel = nullptr;
|
||||||
} else if (!channel->passwordMatch(client->properties()[property::CLIENT_DEFAULT_CHANNEL_PASSWORD], true) && client->permissionValue(permission::PERMTEST_ORDERED, permission::b_channel_join_ignore_password, channel) < 1) {
|
} else if (!channel->passwordMatch(client->properties()[property::CLIENT_DEFAULT_CHANNEL_PASSWORD], true) && !permission::v2::permission_granted(1, client->calculate_permission(permission::b_channel_join_ignore_password, channel->channelId()))) {
|
||||||
logMessage(this->serverId, "{} Client tried to connect to a channel which is password protected and he hasn't the right password. Channel: {} ({})", CLIENT_STR_LOG_PREFIX_(client), channel->channelId(), channel->name());
|
logMessage(this->serverId, "{} Client tried to connect to a channel which is password protected and he hasn't the right password. Channel: {} ({})", CLIENT_STR_LOG_PREFIX_(client), channel->channelId(), channel->name());
|
||||||
channel = nullptr;
|
channel = nullptr;
|
||||||
}
|
}
|
||||||
@ -531,10 +531,10 @@ void TSServer::client_move(
|
|||||||
|
|
||||||
auto i_source_channel = s_source_channel->channelId();
|
auto i_source_channel = s_source_channel->channelId();
|
||||||
if(std::find(deleted.begin(), deleted.end(), i_source_channel) == deleted.end()) {
|
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);
|
auto source_channel_sub_power = target->calculate_permission(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)) {
|
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);
|
auto source_channel_sub_power_ignore = target->calculate_permission(permission::b_channel_ignore_subscribe_power, i_source_channel);
|
||||||
if(!DataClient::permission_granted(source_channel_sub_power_ignore, 1, true)) {
|
if(!permission::v2::permission_granted(1, source_channel_sub_power_ignore, true)) {
|
||||||
logTrace(this->serverId, "Force unsubscribing of client {} for channel {}/{}. (Channel switch and no permissions)",
|
logTrace(this->serverId, "Force unsubscribing of client {} for channel {}/{}. (Channel switch and no permissions)",
|
||||||
CLIENT_STR_LOG_PREFIX_(target), s_source_channel->name(),
|
CLIENT_STR_LOG_PREFIX_(target), s_source_channel->name(),
|
||||||
i_source_channel
|
i_source_channel
|
||||||
|
@ -783,9 +783,9 @@ ts_always_inline bool channel_ignore_permission(ts::permission::PermissionType t
|
|||||||
return permission::i_icon_id == type;
|
return permission::i_icon_id == type;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<pair<ts::permission::PermissionType, ts::permission::v2::PermissionFlaggedValue>> TSServer::calculatePermissions2(
|
vector<pair<ts::permission::PermissionType, ts::permission::v2::PermissionFlaggedValue>> TSServer::calculate_permissions(
|
||||||
ClientDbId client_dbid,
|
|
||||||
const std::deque<permission::PermissionType>& permissions,
|
const std::deque<permission::PermissionType>& permissions,
|
||||||
|
ClientDbId client_dbid,
|
||||||
ClientType client_type,
|
ClientType client_type,
|
||||||
ChannelId channel_id,
|
ChannelId channel_id,
|
||||||
bool calculate_granted,
|
bool calculate_granted,
|
||||||
@ -1000,40 +1000,19 @@ vector<pair<ts::permission::PermissionType, ts::permission::v2::PermissionFlagge
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
deque<pair<ts::permission::PermissionType, ts::permission::PermissionValue>> TSServer::calculatePermissions(
|
permission::v2::PermissionFlaggedValue TSServer::calculate_permission(
|
||||||
permission::PermissionTestType test_type,
|
permission::PermissionType permission,
|
||||||
ClientDbId client_dbid,
|
ClientDbId cldbid,
|
||||||
const std::deque<permission::PermissionType>& permissions,
|
ClientType type,
|
||||||
ClientType client_type,
|
ChannelId channel,
|
||||||
const std::shared_ptr<BasicChannel> &channel,
|
bool granted,
|
||||||
std::shared_ptr<CalculateCache> cache) {
|
std::shared_ptr<CalculateCache> cache) {
|
||||||
if(permissions.empty()) return {};
|
auto result = this->calculate_permissions({permission}, cldbid, type, channel, granted, cache);
|
||||||
|
if(result.empty()) return {0, false};
|
||||||
|
|
||||||
auto data = calculatePermissions2(client_dbid, permissions, client_type, channel ? channel->channelId() : 0, false, cache);
|
|
||||||
deque<pair<ts::permission::PermissionType, ts::permission::PermissionValue>> result;
|
|
||||||
for(auto& entry : data)
|
|
||||||
result.emplace_back(entry.first, entry.second.has_value ? entry.second.value : permNotGranted);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
permission::v2::PermissionFlaggedValue TSServer::calculatePermission2(ts::permission::PermissionType permission, ts::ClientDbId cldbid, ts::server::ClientType type, ts::ChannelId channel, std::shared_ptr<CalculateCache> cache) {
|
|
||||||
auto result = this->calculatePermissions2(cldbid, {permission}, type, channel, false, cache);
|
|
||||||
if(result.empty()) return {permNotGranted, false};
|
|
||||||
return result.front().second;
|
return result.front().second;
|
||||||
}
|
}
|
||||||
|
|
||||||
ts::permission::PermissionValue TSServer::calculatePermission(permission::PermissionTestType test, ClientDbId cldbid, permission::PermissionType permission, ClientType client_type, const std::shared_ptr<BasicChannel>& channel, std::shared_ptr<CalculateCache> cache) {
|
|
||||||
auto result = this->calculatePermissions(test, cldbid, {permission}, client_type, channel, cache);
|
|
||||||
if(result.empty()) return permNotGranted;
|
|
||||||
return result.front().second;
|
|
||||||
}
|
|
||||||
|
|
||||||
ts::permission::PermissionValue TSServer::calculatePermissionGrant(permission::PermissionTestType test, ClientDbId cldbid, permission::PermissionType permission, ClientType client_type, const std::shared_ptr<BasicChannel>& channel) {
|
|
||||||
auto result = this->calculatePermissions2(cldbid, {permission}, client_type, channel ? channel->channelId() : 0, true, nullptr);
|
|
||||||
assert(!result.empty());
|
|
||||||
return result[0].second.has_value ? result[0].second.value : permNotGranted;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TSServer::verifyServerPassword(std::string password, bool hashed) {
|
bool TSServer::verifyServerPassword(std::string password, bool hashed) {
|
||||||
if(!this->properties()[property::VIRTUALSERVER_FLAG_PASSWORD].as<bool>()) return true;
|
if(!this->properties()[property::VIRTUALSERVER_FLAG_PASSWORD].as<bool>()) return true;
|
||||||
if(password.empty()) return false;
|
if(password.empty()) return false;
|
||||||
|
@ -208,27 +208,24 @@ namespace ts {
|
|||||||
std::shared_ptr<VoiceServer> getVoiceServer(){ return this->udpVoiceServer; }
|
std::shared_ptr<VoiceServer> getVoiceServer(){ return this->udpVoiceServer; }
|
||||||
WebControlServer* getWebServer(){ return this->webControlServer; }
|
WebControlServer* getWebServer(){ return this->webControlServer; }
|
||||||
|
|
||||||
std::deque<std::pair<permission::PermissionType, permission::PermissionValue>> calculatePermissions(
|
/* calculate permissions for an client in this server */
|
||||||
permission::PermissionTestType,
|
permission::v2::PermissionFlaggedValue calculate_permission(
|
||||||
|
permission::PermissionType,
|
||||||
ClientDbId,
|
ClientDbId,
|
||||||
const std::deque<permission::PermissionType>&,
|
|
||||||
ClientType type,
|
ClientType type,
|
||||||
const std::shared_ptr<BasicChannel>& channel,
|
ChannelId channel,
|
||||||
std::shared_ptr<CalculateCache> cache = nullptr);
|
bool granted = false,
|
||||||
|
std::shared_ptr<CalculateCache> cache = nullptr
|
||||||
|
);
|
||||||
|
|
||||||
std::vector<std::pair<permission::PermissionType, permission::v2::PermissionFlaggedValue>> calculatePermissions2(
|
std::vector<std::pair<permission::PermissionType, permission::v2::PermissionFlaggedValue>> calculate_permissions(
|
||||||
ClientDbId /* client db id */,
|
const std::deque<permission::PermissionType>&,
|
||||||
const std::deque<permission::PermissionType>& /* permissions to calculate */,
|
ClientDbId,
|
||||||
ClientType type /* client type for default permissions */,
|
ClientType type,
|
||||||
ChannelId /* target channel id */,
|
ChannelId channel,
|
||||||
bool /* calculate granted */,
|
bool granted = false,
|
||||||
std::shared_ptr<CalculateCache> cache = nullptr /* calculate cache */);
|
std::shared_ptr<CalculateCache> cache = nullptr
|
||||||
|
);
|
||||||
permission::PermissionValue calculatePermission(permission::PermissionTestType, ClientDbId, permission::PermissionType, ClientType type, const std::shared_ptr<BasicChannel>& channel, std::shared_ptr<CalculateCache> cache = nullptr);
|
|
||||||
|
|
||||||
permission::v2::PermissionFlaggedValue calculatePermission2(permission::PermissionType, ClientDbId, ClientType type, ChannelId channel, std::shared_ptr<CalculateCache> cache = nullptr);
|
|
||||||
|
|
||||||
permission::PermissionValue calculatePermissionGrant(permission::PermissionTestType, ClientDbId, permission::PermissionType, ClientType type, const std::shared_ptr<BasicChannel>& channel);
|
|
||||||
|
|
||||||
bool verifyServerPassword(std::string, bool hashed = false);
|
bool verifyServerPassword(std::string, bool hashed = false);
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ std::deque<std::shared_ptr<ViewEntry>> ClientChannelView::insert_channels(shared
|
|||||||
std::deque<std::shared_ptr<ViewEntry>> result;
|
std::deque<std::shared_ptr<ViewEntry>> result;
|
||||||
|
|
||||||
if(!cache && test_permissions) cache = make_shared<CalculateCache>();
|
if(!cache && test_permissions) cache = make_shared<CalculateCache>();
|
||||||
bool has_perm = !test_permissions || owner->permissionGranted(permission::PERMTEST_ORDERED, permission::b_channel_ignore_view_power, 1, nullptr, true, cache);
|
bool has_perm = !test_permissions || permission::v2::permission_granted(1, owner->calculate_permission(permission::b_channel_ignore_view_power, 0, false, cache));
|
||||||
bool first = true;
|
bool first = true;
|
||||||
while(head) {
|
while(head) {
|
||||||
if(!first && first_only) break;
|
if(!first && first_only) break;
|
||||||
@ -145,7 +145,7 @@ std::deque<std::shared_ptr<ViewEntry>> ClientChannelView::insert_channels(shared
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!has_perm) {
|
if(!has_perm) {
|
||||||
if(!channel->permission_granted(permission::i_channel_needed_view_power, this->owner->calculate_permission_value(permission::i_channel_view_power, channel->channelId()), false)) {
|
if(!channel->permission_granted(permission::i_channel_needed_view_power, this->owner->calculate_permission(permission::i_channel_view_power, channel->channelId()), false)) {
|
||||||
head = head->next;
|
head = head->next;
|
||||||
debugMessage(this->getServerId(), "{}[CHANNEL] Dropping channel {} ({}) (No permissions)", CLIENT_STR_LOG_PREFIX_(this->owner), channel->channelId(), channel->name());
|
debugMessage(this->getServerId(), "{}[CHANNEL] Dropping channel {} ({}) (No permissions)", CLIENT_STR_LOG_PREFIX_(this->owner), channel->channelId(), channel->name());
|
||||||
continue;
|
continue;
|
||||||
@ -245,7 +245,7 @@ std::deque<std::shared_ptr<ViewEntry>> ClientChannelView::test_channel(std::shar
|
|||||||
if(!cache) cache = make_shared<CalculateCache>();
|
if(!cache) cache = make_shared<CalculateCache>();
|
||||||
|
|
||||||
std::deque<std::shared_ptr<ViewEntry>> result;
|
std::deque<std::shared_ptr<ViewEntry>> result;
|
||||||
bool has_perm = owner->permissionGranted(permission::PERMTEST_ORDERED, permission::b_channel_ignore_view_power, 1, nullptr, true, cache);
|
bool has_perm = permission::v2::permission_granted(1, owner->calculate_permission(permission::b_channel_ignore_view_power, 0, false, cache));
|
||||||
if(has_perm) return {};
|
if(has_perm) return {};
|
||||||
|
|
||||||
deque<shared_ptr<TreeView::LinkedTreeEntry>> parents = {l_old};
|
deque<shared_ptr<TreeView::LinkedTreeEntry>> parents = {l_old};
|
||||||
@ -267,7 +267,7 @@ std::deque<std::shared_ptr<ViewEntry>> ClientChannelView::test_channel(std::shar
|
|||||||
auto channel = dynamic_pointer_cast<BasicChannel>(l_entry->entry);
|
auto channel = dynamic_pointer_cast<BasicChannel>(l_entry->entry);
|
||||||
sassert(entry->channelId() == channel->channelId());
|
sassert(entry->channelId() == channel->channelId());
|
||||||
|
|
||||||
if(!channel->permission_granted(permission::i_channel_needed_view_power, this->owner->calculate_permission_value(permission::i_channel_view_power, channel->channelId()), false)) {
|
if(!channel->permission_granted(permission::i_channel_needed_view_power, this->owner->calculate_permission(permission::i_channel_view_power, channel->channelId()), false)) {
|
||||||
|
|
||||||
for(const auto& te : this->delete_entry(entry))
|
for(const auto& te : this->delete_entry(entry))
|
||||||
result.push_back(dynamic_pointer_cast<ViewEntry>(te));
|
result.push_back(dynamic_pointer_cast<ViewEntry>(te));
|
||||||
@ -288,7 +288,7 @@ std::deque<std::pair<bool, std::shared_ptr<ViewEntry>>> ClientChannelView::updat
|
|||||||
std::deque<std::pair<bool, std::shared_ptr<ViewEntry>>> ClientChannelView::update_channel_path(std::shared_ptr<ts::TreeView::LinkedTreeEntry> l_channel, std::shared_ptr<ts::TreeView::LinkedTreeEntry> l_own, shared_ptr<CalculateCache> cache, ssize_t length) {
|
std::deque<std::pair<bool, std::shared_ptr<ViewEntry>>> ClientChannelView::update_channel_path(std::shared_ptr<ts::TreeView::LinkedTreeEntry> l_channel, std::shared_ptr<ts::TreeView::LinkedTreeEntry> l_own, shared_ptr<CalculateCache> cache, ssize_t length) {
|
||||||
if(!cache) cache = make_shared<CalculateCache>();
|
if(!cache) cache = make_shared<CalculateCache>();
|
||||||
std::deque<std::pair<bool, std::shared_ptr<ViewEntry>>> result;
|
std::deque<std::pair<bool, std::shared_ptr<ViewEntry>>> result;
|
||||||
bool has_perm = owner->permissionGranted(permission::PERMTEST_ORDERED, permission::b_channel_ignore_view_power, 1, nullptr, true, cache);
|
bool has_perm = permission::v2::permission_granted(1, owner->calculate_permission(permission::b_channel_ignore_view_power, 0, false, cache));
|
||||||
|
|
||||||
while(l_channel && length-- != 0) {
|
while(l_channel && length-- != 0) {
|
||||||
auto b_channel = dynamic_pointer_cast<BasicChannel>(l_channel->entry);
|
auto b_channel = dynamic_pointer_cast<BasicChannel>(l_channel->entry);
|
||||||
@ -303,7 +303,7 @@ std::deque<std::pair<bool, std::shared_ptr<ViewEntry>>> ClientChannelView::updat
|
|||||||
visible = true;
|
visible = true;
|
||||||
|
|
||||||
if(!has_perm) {
|
if(!has_perm) {
|
||||||
if(!b_channel->permission_granted(permission::i_channel_needed_view_power, this->owner->calculate_permission_value(permission::i_channel_view_power, b_channel->channelId()), false)) {
|
if(!b_channel->permission_granted(permission::i_channel_needed_view_power, this->owner->calculate_permission(permission::i_channel_view_power, b_channel->channelId()), false)) {
|
||||||
visible = false;
|
visible = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -341,9 +341,9 @@ std::deque<std::pair<ClientChannelView::ChannelAction, std::shared_ptr<ViewEntry
|
|||||||
if(!l_entry) { //Channel not visible yet
|
if(!l_entry) { //Channel not visible yet
|
||||||
if(!l_parent && parent) return {}; //The invisible channel was moved into an invisible tree
|
if(!l_parent && parent) return {}; //The invisible channel was moved into an invisible tree
|
||||||
|
|
||||||
bool has_perm = owner->permissionGranted(permission::PERMTEST_ORDERED, permission::b_channel_ignore_view_power, 1, nullptr);
|
bool has_perm = permission::v2::permission_granted(1, owner->calculate_permission(permission::b_channel_ignore_view_power, 0, false));
|
||||||
if(!has_perm) {
|
if(!has_perm) {
|
||||||
has_perm = dynamic_pointer_cast<BasicChannel>(channel->entry)->permission_granted(permission::i_channel_needed_view_power, this->owner->calculate_permission_value(permission::i_channel_view_power, dynamic_pointer_cast<BasicChannel>(channel->entry)->channelId()), false);
|
has_perm = dynamic_pointer_cast<BasicChannel>(channel->entry)->permission_granted(permission::i_channel_needed_view_power, this->owner->calculate_permission(permission::i_channel_view_power, dynamic_pointer_cast<BasicChannel>(channel->entry)->channelId()), false);
|
||||||
}
|
}
|
||||||
if(!has_perm) return {}; //Channel wasn't visible and he still has no permission for that :)
|
if(!has_perm) return {}; //Channel wasn't visible and he still has no permission for that :)
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ namespace ts {
|
|||||||
|
|
||||||
bool subscribed = false;
|
bool subscribed = false;
|
||||||
bool editable = false;
|
bool editable = false;
|
||||||
bool joinable = false; /* used within notify text message */
|
permission::PermissionType join_permission_error = permission::unknown; /* used within notify text message */
|
||||||
ChannelId previous_channel = 0;
|
ChannelId previous_channel = 0;
|
||||||
uint16_t join_state_id = 0; /* the calculation id for the flag joinable. If this does not match with the join_state_id within the client the flag needs to be recalculated */
|
uint16_t join_state_id = 0; /* the calculation id for the flag joinable. If this does not match with the join_state_id within the client the flag needs to be recalculated */
|
||||||
std::weak_ptr<BasicChannel> handle;
|
std::weak_ptr<BasicChannel> handle;
|
||||||
|
@ -85,20 +85,20 @@ void ConnectedClient::updateChannelClientProperties(bool lock_channel_tree, bool
|
|||||||
/* this->server may be null! */
|
/* this->server may be null! */
|
||||||
shared_ptr<TSServer> server_ref = this->server;
|
shared_ptr<TSServer> server_ref = this->server;
|
||||||
|
|
||||||
auto permissions = this->permissionValues(permission::PERMTEST_ORDERED, {
|
auto permissions = this->calculate_permissions({
|
||||||
permission::i_client_talk_power,
|
permission::i_client_talk_power,
|
||||||
permission::b_client_is_priority_speaker,
|
permission::b_client_is_priority_speaker,
|
||||||
permission::b_client_ignore_antiflood,
|
permission::b_client_ignore_antiflood,
|
||||||
permission::i_channel_view_power,
|
permission::i_channel_view_power,
|
||||||
permission::b_channel_ignore_view_power
|
permission::b_channel_ignore_view_power
|
||||||
}, this->currentChannel);
|
}, this->currentChannel ? this->currentChannel->channelId() : 0);
|
||||||
|
|
||||||
permission::PermissionValue
|
permission::v2::PermissionFlaggedValue
|
||||||
permission_talk_power = permNotGranted,
|
permission_talk_power{0, false},
|
||||||
permission_priority_speaker = permNotGranted,
|
permission_priority_speaker{0, false},
|
||||||
permission_ignore_antiflood = permNotGranted,
|
permission_ignore_antiflood{0, false},
|
||||||
permission_channel_view_power = permNotGranted,
|
permission_channel_view_power{0, false},
|
||||||
permission_channel_ignore_view_power = permNotGranted;
|
permission_channel_ignore_view_power{0, false};
|
||||||
for(const auto& perm : permissions) {
|
for(const auto& perm : permissions) {
|
||||||
if(perm.first == permission::i_client_talk_power)
|
if(perm.first == permission::i_client_talk_power)
|
||||||
permission_talk_power = perm.second;
|
permission_talk_power = perm.second;
|
||||||
@ -113,18 +113,15 @@ void ConnectedClient::updateChannelClientProperties(bool lock_channel_tree, bool
|
|||||||
else sassert(false);
|
else sassert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(permission_talk_power < -2) permission_talk_power = -2;
|
|
||||||
else if(permission_talk_power == -2) permission_talk_power = 0;
|
|
||||||
|
|
||||||
deque<property::ClientProperties> notifyList;
|
deque<property::ClientProperties> notifyList;
|
||||||
debugMessage(this->getServerId(), "{} Got a channel talk power of {} Talk power set is {}", CLIENT_STR_LOG_PREFIX, permission_talk_power, this->properties()[property::CLIENT_TALK_POWER].as<uint64_t>());
|
debugMessage(this->getServerId(), "{} Got a channel talk power of {} Talk power set is {}", CLIENT_STR_LOG_PREFIX, permission_talk_power, this->properties()[property::CLIENT_TALK_POWER].as<uint64_t>());
|
||||||
if(permission_talk_power != this->properties()[property::CLIENT_TALK_POWER].as<uint64_t>()) { //We do not have to update tp if there's no channel
|
if((permission_talk_power.has_value ? permission_talk_power.value : 0) != this->properties()[property::CLIENT_TALK_POWER].as<uint64_t>()) { //We do not have to update tp if there's no channel
|
||||||
this->properties()[property::CLIENT_TALK_POWER] = permission_talk_power;
|
this->properties()[property::CLIENT_TALK_POWER] = (permission_talk_power.has_value ? permission_talk_power.value : 0);
|
||||||
notifyList.emplace_back(property::CLIENT_TALK_POWER);
|
notifyList.emplace_back(property::CLIENT_TALK_POWER);
|
||||||
|
|
||||||
auto update = this->properties()[property::CLIENT_IS_TALKER].as<bool>() || this->properties()[property::CLIENT_TALK_REQUEST].as<int64_t>() > 0;
|
auto update = this->properties()[property::CLIENT_IS_TALKER].as<bool>() || this->properties()[property::CLIENT_TALK_REQUEST].as<int64_t>() > 0;
|
||||||
if(update && this->currentChannel) {
|
if(update && this->currentChannel) {
|
||||||
if(this->currentChannel->talk_power_granted({permission_talk_power, permission_talk_power != permNotGranted})) {
|
if(this->currentChannel->talk_power_granted(permission_talk_power)) {
|
||||||
this->properties()[property::CLIENT_IS_TALKER] = 0;
|
this->properties()[property::CLIENT_IS_TALKER] = 0;
|
||||||
this->properties()[property::CLIENT_TALK_REQUEST] = 0;
|
this->properties()[property::CLIENT_TALK_REQUEST] = 0;
|
||||||
this->properties()[property::CLIENT_TALK_REQUEST_MSG] = "";
|
this->properties()[property::CLIENT_TALK_REQUEST_MSG] = "";
|
||||||
@ -164,16 +161,16 @@ void ConnectedClient::updateChannelClientProperties(bool lock_channel_tree, bool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto pSpeaker = permission_priority_speaker > 0;
|
auto pSpeaker = permission_priority_speaker.has_value && permission_priority_speaker.value > 0;
|
||||||
if(properties()[property::CLIENT_IS_PRIORITY_SPEAKER].as<bool>() != pSpeaker){
|
if(properties()[property::CLIENT_IS_PRIORITY_SPEAKER].as<bool>() != pSpeaker){
|
||||||
properties()[property::CLIENT_IS_PRIORITY_SPEAKER] = pSpeaker;
|
properties()[property::CLIENT_IS_PRIORITY_SPEAKER] = pSpeaker;
|
||||||
notifyList.emplace_back(property::CLIENT_IS_PRIORITY_SPEAKER);
|
notifyList.emplace_back(property::CLIENT_IS_PRIORITY_SPEAKER);
|
||||||
}
|
}
|
||||||
|
|
||||||
block_flood = permission_ignore_antiflood <= 0 || permission_ignore_antiflood == permNotGranted;
|
block_flood = !!permission_ignore_antiflood.has_value || permission_ignore_antiflood.value <= 0;
|
||||||
if(server_ref)
|
if(server_ref)
|
||||||
server_ref->notifyClientPropertyUpdates(_this.lock(), notifyList, notify_self);
|
server_ref->notifyClientPropertyUpdates(_this.lock(), notifyList, notify_self);
|
||||||
this->updateTalkRights(permission_talk_power);
|
this->updateTalkRights(permission_talk_power.has_value ? permission_talk_power.value : 0);
|
||||||
|
|
||||||
if((this->channels_view_power != permission_channel_view_power || this->channels_ignore_view != permission_channel_ignore_view_power) && notify_self && this->currentChannel && server_ref) {
|
if((this->channels_view_power != permission_channel_view_power || this->channels_ignore_view != permission_channel_ignore_view_power) && notify_self && this->currentChannel && server_ref) {
|
||||||
this->channels_view_power = permission_channel_view_power;
|
this->channels_view_power = permission_channel_view_power;
|
||||||
@ -229,7 +226,7 @@ std::deque<std::shared_ptr<BasicChannel>> ConnectedClient::subscribeChannel(cons
|
|||||||
if(!ref_server)
|
if(!ref_server)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
auto general_granted = enforce || this->permission_granted(this->permissionValue(permission::b_channel_ignore_subscribe_power, nullptr), 1, true);
|
auto general_granted = enforce || permission::v2::permission_granted(1, this->calculate_permission(permission::b_channel_ignore_subscribe_power, 0));
|
||||||
{
|
{
|
||||||
shared_lock server_channel_lock(ref_server->channel_tree_lock, defer_lock);
|
shared_lock server_channel_lock(ref_server->channel_tree_lock, defer_lock);
|
||||||
unique_lock client_channel_lock(this->channel_lock, defer_lock);
|
unique_lock client_channel_lock(this->channel_lock, defer_lock);
|
||||||
@ -245,10 +242,10 @@ std::deque<std::shared_ptr<BasicChannel>> ConnectedClient::subscribeChannel(cons
|
|||||||
if(local_channel->subscribed) continue; //Already subscribed
|
if(local_channel->subscribed) continue; //Already subscribed
|
||||||
|
|
||||||
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(permission::i_channel_subscribe_power, channel->channelId());
|
||||||
|
|
||||||
if(!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(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;
|
||||||
}
|
}
|
||||||
@ -564,9 +561,9 @@ bool ConnectedClient::notifyClientNeededPermissions() {
|
|||||||
cache_lock.unlock();
|
cache_lock.unlock();
|
||||||
|
|
||||||
for(const auto& value : permissions) {
|
for(const auto& value : permissions) {
|
||||||
if(value.second != permNotGranted || value.first == permission::b_client_force_push_to_talk) {
|
if(value.second.has_value) {
|
||||||
cmd[index]["permid"] = value.first;
|
cmd[index]["permid"] = value.first;
|
||||||
cmd[index++]["permvalue"] = value.second == permNotGranted ? 0 : value.second;
|
cmd[index++]["permvalue"] = value.second.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(permissions.empty()) {
|
if(permissions.empty()) {
|
||||||
@ -591,6 +588,8 @@ bool ConnectedClient::notifyError(const command_result& result, const std::strin
|
|||||||
} else {
|
} else {
|
||||||
cmd["id"] = (int) result.error_code();
|
cmd["id"] = (int) result.error_code();
|
||||||
cmd["msg"] = findError(result.error_code()).message;
|
cmd["msg"] = findError(result.error_code()).message;
|
||||||
|
if(result.is_permission_error())
|
||||||
|
cmd["failed_permid"] = result.permission_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(retCode.length() > 0)
|
if(retCode.length() > 0)
|
||||||
@ -616,7 +615,7 @@ inline void send_channels(ConnectedClient* client, ChannelIT begin, const Channe
|
|||||||
if(begin == end)
|
if(begin == end)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Command channellist("channellist");
|
ts::command_builder builder{"channellist", 512, 6};
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
|
|
||||||
while(begin != end) {
|
while(begin != end) {
|
||||||
@ -625,9 +624,9 @@ inline void send_channels(ConnectedClient* client, ChannelIT begin, const Channe
|
|||||||
|
|
||||||
for (const auto &elm : channel->properties().list_properties(property::FLAG_CHANNEL_VIEW, client->getType() == CLIENT_TEAMSPEAK ? property::FLAG_NEW : (uint16_t) 0)) {
|
for (const auto &elm : channel->properties().list_properties(property::FLAG_CHANNEL_VIEW, client->getType() == CLIENT_TEAMSPEAK ? property::FLAG_NEW : (uint16_t) 0)) {
|
||||||
if(elm.type() == property::CHANNEL_ORDER)
|
if(elm.type() == property::CHANNEL_ORDER)
|
||||||
channellist[index][elm.type().name] = override_orderid ? 0 : (*begin)->previous_channel;
|
builder.put_unchecked(index, elm.type().name, override_orderid ? 0 : (*begin)->previous_channel);
|
||||||
else
|
else
|
||||||
channellist[index][elm.type().name] = elm.as<string>();
|
builder.put_unchecked(index, elm.type().name, elm.as<string>());
|
||||||
}
|
}
|
||||||
|
|
||||||
begin++;
|
begin++;
|
||||||
@ -636,9 +635,9 @@ inline void send_channels(ConnectedClient* client, ChannelIT begin, const Channe
|
|||||||
}
|
}
|
||||||
if(dynamic_cast<VoiceClient*>(client)) {
|
if(dynamic_cast<VoiceClient*>(client)) {
|
||||||
auto vc = dynamic_cast<VoiceClient*>(client);
|
auto vc = dynamic_cast<VoiceClient*>(client);
|
||||||
vc->sendCommand0(channellist, false, true); /* we need to process this command directly so it will be processed before the channellistfinished stuff */
|
vc->sendCommand0(builder.build(), false, true); /* we need to process this command directly so it will be processed before the channellistfinished stuff */
|
||||||
} else {
|
} else {
|
||||||
client->sendCommand(channellist);
|
client->sendCommand(builder);
|
||||||
}
|
}
|
||||||
if(begin != end)
|
if(begin != end)
|
||||||
send_channels(client, begin, end, override_orderid);
|
send_channels(client, begin, end, override_orderid);
|
||||||
@ -785,7 +784,7 @@ void ConnectedClient::sendServerInit() {
|
|||||||
command["acn"] = this->getDisplayName();
|
command["acn"] = this->getDisplayName();
|
||||||
command["aclid"] = this->getClientId();
|
command["aclid"] = this->getClientId();
|
||||||
if(dynamic_cast<VoiceClient*>(this)) {
|
if(dynamic_cast<VoiceClient*>(this)) {
|
||||||
dynamic_cast<VoiceClient*>(this)->sendCommand0(command, false, true); /* process it directly so the order for the channellist entries is ensured. (First serverinit then everything else) */
|
dynamic_cast<VoiceClient*>(this)->sendCommand0(command.build(), false, true); /* process it directly so the order for the channellist entries is ensured. (First serverinit then everything else) */
|
||||||
} else {
|
} else {
|
||||||
this->sendCommand(command);
|
this->sendCommand(command);
|
||||||
}
|
}
|
||||||
@ -851,7 +850,7 @@ bool ConnectedClient::handleCommandFull(Command& cmd, bool disconnectOnFail) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<BanRecord> ConnectedClient::resolveActiveBan(const std::string& ip_address) {
|
std::shared_ptr<BanRecord> ConnectedClient::resolveActiveBan(const std::string& ip_address) {
|
||||||
if(this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_client_ignore_bans, 1)) return nullptr;
|
if(permission::v2::permission_granted(1, this->calculate_permission(permission::b_client_ignore_bans, 0))) return nullptr;
|
||||||
|
|
||||||
//Check if manager banned
|
//Check if manager banned
|
||||||
auto banManager = serverInstance->banManager();
|
auto banManager = serverInstance->banManager();
|
||||||
@ -901,44 +900,37 @@ std::shared_ptr<BanRecord> ConnectedClient::resolveActiveBan(const std::string&
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ConnectedClient::update_cached_permissions() {
|
bool ConnectedClient::update_cached_permissions() {
|
||||||
auto values = this->permissionValues(permission::PERMTEST_ORDERED, permission::neededPermissions, shared_ptr(this->currentChannel)); /* copy the channel here so it does not change */
|
auto values = this->calculate_permissions(permission::neededPermissions, this->currentChannel? this->currentChannel->channelId() : 0); /* copy the channel here so it does not change */
|
||||||
auto updated = false;
|
auto updated = false;
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
lock_guard cached_lock(this->cached_permissions_lock);
|
lock_guard cached_lock(this->cached_permissions_lock);
|
||||||
|
|
||||||
vector<permission::PermissionType> old_permissions;
|
auto old_cached_permissions{this->cached_permissions};
|
||||||
old_permissions.reserve(this->cached_permissions.size());
|
this->cached_permissions = values;
|
||||||
|
std::sort(this->cached_permissions.begin(), this->cached_permissions.end(), [](const auto& a, const auto& b) { return a.first < b.first; });
|
||||||
|
|
||||||
for(const auto& value : this->cached_permissions)
|
if(this->cached_permissions.size() != old_cached_permissions.size())
|
||||||
old_permissions.push_back(value.first);
|
updated = true;
|
||||||
|
else {
|
||||||
for(const auto& value : values) {
|
for(auto oit = old_cached_permissions.begin(), nit = this->cached_permissions.begin(); oit != old_cached_permissions.end(); oit++, nit++) {
|
||||||
auto value_it = cached_permissions.find(value.first);
|
if(oit->first != nit->first || oit->second != nit->second) {
|
||||||
if(value_it == cached_permissions.end()) { /* new entry */
|
updated = true;
|
||||||
updated = true;
|
break;
|
||||||
this->cached_permissions[value.first] = value.second;
|
}
|
||||||
continue; /* no need to remove that from old_permissions because it isn't there */
|
|
||||||
} else if(value_it->second != value.second) { /* entry changed */
|
|
||||||
updated = true;
|
|
||||||
value_it->second = value.second;
|
|
||||||
}
|
|
||||||
|
|
||||||
{ /* we've updated the value or verified it */
|
|
||||||
auto old_it = find(old_permissions.begin(), old_permissions.end(), value.first);
|
|
||||||
if(old_it != old_permissions.end())
|
|
||||||
old_permissions.erase(old_it);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for(const auto& left : old_permissions) {
|
this->cpmerission_whisper_power = {0, false};
|
||||||
auto value_it = cached_permissions.find(left);
|
this->cpmerission_needed_whisper_power = {0, false};
|
||||||
if(value_it != cached_permissions.end()) {
|
for(const auto& entry : values) {
|
||||||
cached_permissions.erase(value_it);
|
if(entry.first == permission::i_client_whisper_power)
|
||||||
updated = true;
|
this->cpmerission_whisper_power = entry.second;
|
||||||
}
|
else
|
||||||
}
|
if(entry.first == permission::i_client_needed_whisper_power)
|
||||||
|
this->cpmerission_needed_whisper_power = entry.second;
|
||||||
}
|
}
|
||||||
|
|
||||||
return updated;
|
return updated;
|
||||||
@ -954,72 +946,47 @@ void ConnectedClient::sendTSPermEditorWarning() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
permission::v2::PermissionFlaggedValue ConnectedClient::calculate_permission_value(const ts::permission::PermissionType &permission, ts::ChannelId channel_id) {
|
#define RESULT(perm_) \
|
||||||
if(channel_id == (this->currentChannel ? this->currentChannel->channelId() : 0) || channel_id == -1) {
|
|
||||||
std::lock_guard lock(this->cached_permissions_lock);
|
|
||||||
auto index = this->cached_permissions.find(permission);
|
|
||||||
if(index != this->cached_permissions.end())
|
|
||||||
return {index->second, index->second != permNotGranted};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto ref_server = this->server;
|
|
||||||
if(ref_server) {
|
|
||||||
auto result = this->server->calculatePermissions2(this->getClientDatabaseId(), {permission}, this->getType(), channel_id, false);
|
|
||||||
if(!result.empty()) /* it should never be empty! */
|
|
||||||
return result.back().second;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto value = this->permissionValue(permission::PERMTEST_ORDERED, permission, nullptr);
|
|
||||||
return {value, value != permNotGranted};
|
|
||||||
}
|
|
||||||
|
|
||||||
#define RESULT(flag) \
|
|
||||||
do { \
|
do { \
|
||||||
ventry->join_state_id = this->join_state_id; \
|
ventry->join_state_id = this->join_state_id; \
|
||||||
ventry->joinable = (flag); \
|
ventry->join_permission_error = (perm_); \
|
||||||
return flag; \
|
return perm_; \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
bool ConnectedClient::calculate_and_get_join_state(const std::shared_ptr<BasicChannel>& channel) {
|
permission::PermissionType ConnectedClient::calculate_and_get_join_state(const std::shared_ptr<BasicChannel>& channel) {
|
||||||
shared_ptr<ViewEntry> ventry;
|
shared_ptr<ViewEntry> ventry;
|
||||||
{
|
{
|
||||||
shared_lock view_lock(this->channel_lock);
|
shared_lock view_lock(this->channel_lock);
|
||||||
ventry = this->channel_view()->find_channel(channel);
|
ventry = this->channel_view()->find_channel(channel);
|
||||||
if(!ventry)
|
if(!ventry)
|
||||||
return false;
|
return permission::i_channel_view_power;
|
||||||
}
|
}
|
||||||
if(ventry->join_state_id == this->join_state_id)
|
if(ventry->join_state_id == this->join_state_id)
|
||||||
return ventry->joinable;
|
return ventry->join_permission_error;
|
||||||
|
|
||||||
|
auto channel_id = channel->channelId();
|
||||||
auto permission_cache = make_shared<CalculateCache>();
|
auto permission_cache = make_shared<CalculateCache>();
|
||||||
switch(channel->channelType()) {
|
switch(channel->channelType()) {
|
||||||
case ChannelType::permanent:
|
case ChannelType::permanent:
|
||||||
if(!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_channel_join_permanent, 1, channel, true, permission_cache))
|
if(!permission::v2::permission_granted(1, this->calculate_permission(permission::b_channel_join_permanent, channel_id)))
|
||||||
RESULT(false);
|
RESULT(permission::b_channel_join_permanent);
|
||||||
break;
|
break;
|
||||||
case ChannelType::semipermanent:
|
case ChannelType::semipermanent:
|
||||||
if(!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_channel_join_semi_permanent, 1, channel, true, permission_cache))
|
if(!permission::v2::permission_granted(1, this->calculate_permission(permission::b_channel_join_semi_permanent, channel_id)))
|
||||||
RESULT(false);
|
RESULT(permission::b_channel_join_semi_permanent);
|
||||||
break;
|
break;
|
||||||
case ChannelType::temporary:
|
case ChannelType::temporary:
|
||||||
if(!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_channel_join_temporary, 1, channel, true, permission_cache))
|
if(!permission::v2::permission_granted(1, this->calculate_permission(permission::b_channel_join_temporary, channel_id)))
|
||||||
RESULT(false);
|
RESULT(permission::b_channel_join_temporary);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_channel_ignore_join_power, 1, channel, true, permission_cache)) {
|
if(!channel->permission_granted(permission::i_channel_needed_join_power, this->calculate_permission(permission::i_channel_join_power, channel_id), false)) {
|
||||||
auto result = this->server->calculatePermissions2(this->getClientDatabaseId(), {permission::i_channel_join_power}, this->getType(), channel->channelId(), false, permission_cache);
|
if(!permission::v2::permission_granted(1, this->calculate_permission(permission::b_channel_ignore_join_power, channel_id)))
|
||||||
if(result.empty())
|
RESULT(permission::i_channel_join_power);
|
||||||
RESULT(false);
|
|
||||||
|
|
||||||
if(!channel->permission_granted(permission::i_channel_needed_join_power, result.back().second, false))
|
|
||||||
RESULT(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto val = this->permissionValue(permission::PERMTEST_ORDERED, permission::b_client_is_sticky, this->currentChannel, permission_cache);
|
if(permission::v2::permission_granted(1, this->calculate_permission(permission::b_client_is_sticky, this->currentChannel ? this->currentChannel->channelId() : 0)))
|
||||||
if (val != permNotGranted && val > 0) {
|
if(!permission::v2::permission_granted(1, this->calculate_permission(permission::b_client_ignore_sticky, channel_id)))
|
||||||
auto st = this->permissionValue(permission::PERMTEST_ORDERED, permission::b_client_ignore_sticky, this->currentChannel, permission_cache);
|
RESULT(permission::b_client_is_sticky);
|
||||||
if (st != 1)
|
RESULT(permission::unknown);
|
||||||
RESULT(false);
|
|
||||||
}
|
|
||||||
RESULT(true);
|
|
||||||
}
|
}
|
@ -6,6 +6,7 @@
|
|||||||
#include "music/Song.h"
|
#include "music/Song.h"
|
||||||
#include "../channel/ClientChannelView.h"
|
#include "../channel/ClientChannelView.h"
|
||||||
#include "DataClient.h"
|
#include "DataClient.h"
|
||||||
|
#include "query/command3.h"
|
||||||
|
|
||||||
#define CLIENT_STR_LOG_PREFIX_(this) (std::string("[") + this->getLoggingPeerIp() + ":" + std::to_string(this->getPeerPort()) + "/" + this->getDisplayName() + " | " + std::to_string(this->getClientId()) + "]")
|
#define CLIENT_STR_LOG_PREFIX_(this) (std::string("[") + this->getLoggingPeerIp() + ":" + std::to_string(this->getPeerPort()) + "/" + this->getDisplayName() + " | " + std::to_string(this->getClientId()) + "]")
|
||||||
#define CLIENT_STR_LOG_PREFIX CLIENT_STR_LOG_PREFIX_(this)
|
#define CLIENT_STR_LOG_PREFIX CLIENT_STR_LOG_PREFIX_(this)
|
||||||
@ -37,40 +38,6 @@ if(this->shouldFloodBlock()) return command_result{error::ban_flooding};
|
|||||||
#define CMD_CHK_PARM_COUNT(count) \
|
#define CMD_CHK_PARM_COUNT(count) \
|
||||||
if(cmd.bulkCount() != count) return command_result{error::parameter_invalid_count};
|
if(cmd.bulkCount() != count) return command_result{error::parameter_invalid_count};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define PERM_CHECK_CHANNEL_CR(pr, required, channel, req, cache) \
|
|
||||||
do { \
|
|
||||||
if(!this->permissionGranted(permission::PERMTEST_ORDERED, pr, required, channel, req, cache)) {\
|
|
||||||
return command_result{pr}; \
|
|
||||||
}\
|
|
||||||
} while(false)
|
|
||||||
|
|
||||||
//If a permission is required it could not be -1
|
|
||||||
#define PERM_CHECK_CHANNELR(pr, required, channel, req) PERM_CHECK_CHANNEL_CR(pr, required, channel, req, nullptr)
|
|
||||||
|
|
||||||
//If a permission is required it could not be -1
|
|
||||||
#define PERM_CHECK_CHANNEL(pr, required, channel) PERM_CHECK_CHANNELR(pr, required, channel, false)
|
|
||||||
|
|
||||||
#define PERM_CHECKR(pr, required, req) PERM_CHECK_CHANNELR(pr, (required), nullptr, req)
|
|
||||||
#define PERM_CHECK(pr, required) PERM_CHECKR(pr, required, false)
|
|
||||||
|
|
||||||
/* optional parameter required. By default true */
|
|
||||||
#define CACHED_PERM_CHECK(permission_type, required, ...) \
|
|
||||||
do { \
|
|
||||||
if(!this->permission_granted(this->cached_permission_value(permission_type), required, #__VA_ARGS__)) \
|
|
||||||
return command_result{permission_type}; \
|
|
||||||
} while(0)
|
|
||||||
|
|
||||||
//p = permission | target_permission = channel permission | channel = target channel | requires a power
|
|
||||||
|
|
||||||
#define PERM_CHECK_CHANNEL_NEEDED_CR(p, target_permission, channel, req, cache) \
|
|
||||||
this->permissionGranted(permission::PERMTEST_ORDERED, p, (channel)->permissions()->getPermissionValue(permission::PERMTEST_ORDERED, target_permission, nullptr), channel, req, cache)
|
|
||||||
|
|
||||||
#define PERM_CHECK_CHANNEL_NEEDEDR(p, target_permission, channel, req) PERM_CHECK_CHANNEL_NEEDED_CR(p, target_permission, channel, req, nullptr)
|
|
||||||
|
|
||||||
#define PERM_CHECK_CHANNEL_NEEDED(p, target_permission, channel) PERM_CHECK_CHANNEL_NEEDEDR(p, target_permission, channel, true)
|
|
||||||
|
|
||||||
namespace ts {
|
namespace ts {
|
||||||
class GroupManager;
|
class GroupManager;
|
||||||
namespace connection {
|
namespace connection {
|
||||||
@ -120,6 +87,7 @@ namespace ts {
|
|||||||
|
|
||||||
/* Note: Order is not guaranteed here! */
|
/* Note: Order is not guaranteed here! */
|
||||||
virtual void sendCommand(const ts::Command& command, bool low = false) = 0;
|
virtual void sendCommand(const ts::Command& command, bool low = false) = 0;
|
||||||
|
virtual void sendCommand(const ts::command_builder& command, bool low = false) = 0;
|
||||||
|
|
||||||
//General manager stuff
|
//General manager stuff
|
||||||
//FIXME cache the client id for speedup
|
//FIXME cache the client id for speedup
|
||||||
@ -127,6 +95,7 @@ namespace ts {
|
|||||||
virtual void setClientId(uint16_t clId) { properties()[property::CLIENT_ID] = clId; }
|
virtual void setClientId(uint16_t clId) { properties()[property::CLIENT_ID] = clId; }
|
||||||
|
|
||||||
inline std::shared_ptr<BasicChannel> getChannel(){ return this->currentChannel; }
|
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<TSServer> getServer(){ return this->server; }
|
inline std::shared_ptr<TSServer> getServer(){ return this->server; }
|
||||||
inline ServerId getServerId(){ return this->server ? this->server->getServerId() : (ServerId) 0; }
|
inline ServerId getServerId(){ return this->server ? this->server->getServerId() : (ServerId) 0; }
|
||||||
|
|
||||||
@ -289,18 +258,19 @@ namespace ts {
|
|||||||
/*
|
/*
|
||||||
* permission stuff
|
* permission stuff
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
inline permission::PermissionValue cached_permission_value(permission::PermissionType type) const {
|
inline permission::PermissionValue cached_permission_value(permission::PermissionType type) const {
|
||||||
std::lock_guard lock(this->cached_permissions_lock);
|
std::lock_guard lock(this->cached_permissions_lock);
|
||||||
auto index = this->cached_permissions.find(type);
|
auto index = this->cached_permissions.find(type);
|
||||||
if(index != this->cached_permissions.end())
|
if(index != this->cached_permissions.end())
|
||||||
return index->second;
|
return index->second;
|
||||||
|
|
||||||
/* We're only caching permissions which are granted to reduce memory */
|
We're only caching permissions which are granted to reduce memory
|
||||||
//logError(this->getServerId(), "{} Looked up cached permission, which hasn't been cached!", CLIENT_STR_LOG_PREFIX);
|
//logError(this->getServerId(), "{} Looked up cached permission, which hasn't been cached!", CLIENT_STR_LOG_PREFIX);
|
||||||
return permNotGranted;
|
return permNotGranted;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
bool update_cached_permissions();
|
bool update_cached_permissions();
|
||||||
permission::v2::PermissionFlaggedValue calculate_permission_value(const permission::PermissionType& /* permission type */, ChannelId /* target channel */);
|
|
||||||
protected:
|
protected:
|
||||||
std::weak_ptr<ConnectedClient> _this;
|
std::weak_ptr<ConnectedClient> _this;
|
||||||
|
|
||||||
@ -309,7 +279,6 @@ namespace ts {
|
|||||||
ConnectionState state = ConnectionState::UNKNWON;
|
ConnectionState state = ConnectionState::UNKNWON;
|
||||||
sockaddr_storage remote_address;
|
sockaddr_storage remote_address;
|
||||||
|
|
||||||
std::shared_ptr<BasicChannel> currentChannel = nullptr;
|
|
||||||
bool allowedToTalk = false;
|
bool allowedToTalk = false;
|
||||||
|
|
||||||
threads::Mutex disconnectLock;
|
threads::Mutex disconnectLock;
|
||||||
@ -358,23 +327,16 @@ namespace ts {
|
|||||||
std::shared_mutex channel_lock;
|
std::shared_mutex channel_lock;
|
||||||
|
|
||||||
std::mutex cached_permissions_lock;
|
std::mutex cached_permissions_lock;
|
||||||
std::map<permission::PermissionType, permission::PermissionValue> cached_permissions; /* contains all needed permissions which are set */
|
std::vector<std::pair<permission::PermissionType, permission::v2::PermissionFlaggedValue>> cached_permissions; /* contains all needed permissions which are set */
|
||||||
#pragma pack(push, 1)
|
|
||||||
struct CachedPermission {
|
|
||||||
bool flag_skip : 1; /* could be enabled by server / channel or client group. If this flag is set we need no lookup for channel permissions */
|
|
||||||
bool flag_value : 1; /* says if we have a value or not */
|
|
||||||
permission::PermissionValue value;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(CachedPermission) == 5);
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
|
permission::v2::PermissionFlaggedValue channels_view_power{0, false};
|
||||||
permission::PermissionValue channels_view_power = permNotGranted;
|
permission::v2::PermissionFlaggedValue channels_ignore_view{0, false};
|
||||||
permission::PermissionValue channels_ignore_view = permNotGranted;
|
permission::v2::PermissionFlaggedValue cpmerission_whisper_power{0, false};
|
||||||
|
permission::v2::PermissionFlaggedValue cpmerission_needed_whisper_power{0, false};
|
||||||
|
|
||||||
bool subscribeToAll = false;
|
bool subscribeToAll = false;
|
||||||
uint16_t join_state_id = 1; /* default channel value is 0 and by default we need to calculate at least once, so we use 1 */
|
uint16_t join_state_id = 1; /* default channel value is 0 and by default we need to calculate at least once, so we use 1 */
|
||||||
bool calculate_and_get_join_state(const std::shared_ptr<BasicChannel>&);
|
permission::PermissionType calculate_and_get_join_state(const std::shared_ptr<BasicChannel>&);
|
||||||
|
|
||||||
std::weak_ptr<MusicClient> selectedBot;
|
std::weak_ptr<MusicClient> selectedBot;
|
||||||
std::weak_ptr<MusicClient> subscribed_bot;
|
std::weak_ptr<MusicClient> subscribed_bot;
|
||||||
@ -435,13 +397,13 @@ namespace ts {
|
|||||||
command_result handleCommandServerGroupAutoAddPerm(Command&);
|
command_result handleCommandServerGroupAutoAddPerm(Command&);
|
||||||
command_result handleCommandServerGroupAutoDelPerm(Command&);
|
command_result handleCommandServerGroupAutoDelPerm(Command&);
|
||||||
|
|
||||||
command_result handleCommandClientAddPerm(Command&); //TODO: Use cached permission values
|
command_result handleCommandClientAddPerm(Command&);
|
||||||
command_result handleCommandClientDelPerm(Command&); //TODO: Use cached permission values
|
command_result handleCommandClientDelPerm(Command&);
|
||||||
command_result handleCommandClientPermList(Command&); //TODO: Use cached permission values
|
command_result handleCommandClientPermList(Command&);
|
||||||
|
|
||||||
command_result handleCommandChannelClientAddPerm(Command&); //TODO: Use cached permission values
|
command_result handleCommandChannelClientAddPerm(Command&);
|
||||||
command_result handleCommandChannelClientDelPerm(Command&); //TODO: Use cached permission values
|
command_result handleCommandChannelClientDelPerm(Command&);
|
||||||
command_result handleCommandChannelClientPermList(Command&); //TODO: Use cached permission values
|
command_result handleCommandChannelClientPermList(Command&);
|
||||||
|
|
||||||
command_result handleCommandChannelGroupAdd(Command&);
|
command_result handleCommandChannelGroupAdd(Command&);
|
||||||
command_result handleCommandChannelGroupCopy(Command&);
|
command_result handleCommandChannelGroupCopy(Command&);
|
||||||
@ -459,12 +421,12 @@ namespace ts {
|
|||||||
command_result handleCommandClientChatClosed(Command&);
|
command_result handleCommandClientChatClosed(Command&);
|
||||||
|
|
||||||
//File transfare commands
|
//File transfare commands
|
||||||
command_result handleCommandFTGetFileList(Command&); //TODO: Use cached permission values
|
command_result handleCommandFTGetFileList(Command&);
|
||||||
command_result handleCommandFTCreateDir(Command&); //TODO: Use cached permission values
|
command_result handleCommandFTCreateDir(Command&);
|
||||||
command_result handleCommandFTDeleteFile(Command&); //TODO: Use cached permission values
|
command_result handleCommandFTDeleteFile(Command&);
|
||||||
command_result handleCommandFTInitUpload(Command&); //TODO: Use cached permission values
|
command_result handleCommandFTInitUpload(Command&);
|
||||||
command_result handleCommandFTInitDownload(Command&); //TODO: Use cached permission values
|
command_result handleCommandFTInitDownload(Command&);
|
||||||
command_result handleCommandFTGetFileInfo(Command&); //TODO: Use cached permission values
|
command_result handleCommandFTGetFileInfo(Command&);
|
||||||
//CMD_TODO handleCommandFTGetFileInfo -> 5 points
|
//CMD_TODO handleCommandFTGetFileInfo -> 5 points
|
||||||
//CMD_TODO handleCommandFTStop -> 5 points
|
//CMD_TODO handleCommandFTStop -> 5 points
|
||||||
//CMD_TODO handleCommandFTRenameFile -> 5 points
|
//CMD_TODO handleCommandFTRenameFile -> 5 points
|
||||||
@ -527,20 +489,20 @@ namespace ts {
|
|||||||
command_result handleCommandPermFind(Command&);
|
command_result handleCommandPermFind(Command&);
|
||||||
command_result handleCommandPermOverview(Command&);
|
command_result handleCommandPermOverview(Command&);
|
||||||
|
|
||||||
command_result handleCommandChannelFind(Command&); //TODO: Use cached permission values
|
command_result handleCommandChannelFind(Command&);
|
||||||
command_result handleCommandChannelInfo(Command&); //TODO: Use cached permission values
|
command_result handleCommandChannelInfo(Command&);
|
||||||
|
|
||||||
command_result handleCommandMusicBotCreate(Command&); //TODO: Use cached permission values
|
command_result handleCommandMusicBotCreate(Command&);
|
||||||
command_result handleCommandMusicBotDelete(Command&); //TODO: Use cached permission values
|
command_result handleCommandMusicBotDelete(Command&);
|
||||||
command_result handleCommandMusicBotSetSubscription(Command&); //TODO: Use cached permission values
|
command_result handleCommandMusicBotSetSubscription(Command&);
|
||||||
|
|
||||||
command_result handleCommandMusicBotPlayerInfo(Command&); //TODO: Use cached permission values
|
command_result handleCommandMusicBotPlayerInfo(Command&);
|
||||||
command_result handleCommandMusicBotPlayerAction(Command&); //TODO: Use cached permission values
|
command_result handleCommandMusicBotPlayerAction(Command&);
|
||||||
|
|
||||||
command_result handleCommandMusicBotQueueList(Command&); //TODO: Use cached permission values
|
command_result handleCommandMusicBotQueueList(Command&);
|
||||||
command_result handleCommandMusicBotQueueAdd(Command&); //TODO: Use cached permission values
|
command_result handleCommandMusicBotQueueAdd(Command&);
|
||||||
command_result handleCommandMusicBotQueueRemove(Command&); //TODO: Use cached permission values
|
command_result handleCommandMusicBotQueueRemove(Command&);
|
||||||
command_result handleCommandMusicBotQueueReorder(Command&); //TODO: Use cached permission values
|
command_result handleCommandMusicBotQueueReorder(Command&);
|
||||||
|
|
||||||
command_result handleCommandMusicBotPlaylistAssign(Command&);
|
command_result handleCommandMusicBotPlaylistAssign(Command&);
|
||||||
|
|
||||||
@ -561,9 +523,9 @@ namespace ts {
|
|||||||
command_result handleCommandPlaylistSongReorder(Command&);
|
command_result handleCommandPlaylistSongReorder(Command&);
|
||||||
command_result handleCommandPlaylistSongRemove(Command&);
|
command_result handleCommandPlaylistSongRemove(Command&);
|
||||||
|
|
||||||
command_result handleCommandPermReset(Command&); //TODO: Use cached permission values
|
command_result handleCommandPermReset(Command&);
|
||||||
|
|
||||||
command_result handleCommandHelp(Command&); //TODO: Use cached permission values
|
command_result handleCommandHelp(Command&);
|
||||||
|
|
||||||
command_result handleCommandUpdateMyTsId(Command&);
|
command_result handleCommandUpdateMyTsId(Command&);
|
||||||
command_result handleCommandUpdateMyTsData(Command&);
|
command_result handleCommandUpdateMyTsData(Command&);
|
||||||
|
@ -96,7 +96,7 @@ if (!l_channel && (channel_id != 0 || force)) return command_result{error::chann
|
|||||||
/* the "newest" channel permission access test */
|
/* the "newest" channel permission access test */
|
||||||
#define CHANNEL_PERMISSION_TEST(permission_type, permission_needed_type, _channel, permission_required) \
|
#define CHANNEL_PERMISSION_TEST(permission_type, permission_needed_type, _channel, permission_required) \
|
||||||
do { \
|
do { \
|
||||||
auto permission_granted = this->calculate_permission_value(permission_type, _channel->channelId()); \
|
auto permission_granted = this->calculate_permission(permission_type, _channel->channelId()); \
|
||||||
if(!channel->permission_granted(permission_needed_type, permission_granted, permission_required)) \
|
if(!channel->permission_granted(permission_needed_type, permission_granted, permission_required)) \
|
||||||
return command_result{permission_type}; \
|
return command_result{permission_type}; \
|
||||||
} while(0)
|
} while(0)
|
||||||
@ -104,7 +104,7 @@ do { \
|
|||||||
/* the "newest" group permission access test */
|
/* the "newest" group permission access test */
|
||||||
#define GROUP_PERMISSION_TEST(permission_type, permission_needed_type, _group, permission_required) \
|
#define GROUP_PERMISSION_TEST(permission_type, permission_needed_type, _group, permission_required) \
|
||||||
do { \
|
do { \
|
||||||
auto permission_granted = this->calculate_permission_value(permission_type, 0); \
|
auto permission_granted = this->calculate_permission(permission_type, 0); \
|
||||||
if(!_group->permission_granted(permission_needed_type, permission_granted, permission_required)) \
|
if(!_group->permission_granted(permission_needed_type, permission_granted, permission_required)) \
|
||||||
return command_result{permission_type}; \
|
return command_result{permission_type}; \
|
||||||
} while(0)
|
} while(0)
|
||||||
@ -375,7 +375,7 @@ command_result ConnectedClient::handleCommand(Command &cmd) {
|
|||||||
if (this->getType() == ClientType::CLIENT_QUERY) return command_result{error::command_not_found}; //Dont log query invalid commands
|
if (this->getType() == ClientType::CLIENT_QUERY) return command_result{error::command_not_found}; //Dont log query invalid commands
|
||||||
if (this->getType() == ClientType::CLIENT_TEAMSPEAK)
|
if (this->getType() == ClientType::CLIENT_TEAMSPEAK)
|
||||||
if (command.empty() || command.find_first_not_of(' ') == -1) {
|
if (command.empty() || command.find_first_not_of(' ') == -1) {
|
||||||
if (!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_client_allow_invalid_packet, 1, this->currentChannel))
|
if (!this->permissionGranted(permission::b_client_allow_invalid_packet, 1, this->currentChannel))
|
||||||
((VoiceClient *) this)->disconnect(VREASON_SERVER_KICK, config::messages::kick_invalid_command, this->server ? this->server->serverAdmin : static_pointer_cast<ConnectedClient>(serverInstance->getInitialServerAdmin()), true);
|
((VoiceClient *) this)->disconnect(VREASON_SERVER_KICK, config::messages::kick_invalid_command, this->server ? this->server->serverAdmin : static_pointer_cast<ConnectedClient>(serverInstance->getInitialServerAdmin()), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -391,19 +391,19 @@ command_result ConnectedClient::handleCommandServerGetVariables(Command &cmd) {
|
|||||||
|
|
||||||
#define SERVEREDIT_CHK_PROP(name, perm, type)\
|
#define SERVEREDIT_CHK_PROP(name, perm, type)\
|
||||||
else if(key == name) { \
|
else if(key == name) { \
|
||||||
if(!permissionGranted(permission::PERMTEST_HIGHEST, perm, 1, nullptr, true, cache, target_server, true)) return command_result{perm}; \
|
if(!permissionGranted(perm, 1, nullptr, true, cache, target_server, true)) return command_result{perm}; \
|
||||||
if(toApplay.count(key) == 0) toApplay[key] = cmd[key].as<std::string>(); \
|
if(toApplay.count(key) == 0) toApplay[key] = cmd[key].as<std::string>(); \
|
||||||
if(!cmd[0][key].castable<type>()) return command_result{error::parameter_invalid};
|
if(!cmd[0][key].castable<type>()) return command_result{error::parameter_invalid};
|
||||||
|
|
||||||
#define SERVEREDIT_CHK_PROP_CACHED(name, perm, type)\
|
#define SERVEREDIT_CHK_PROP_CACHED(name, perm, type)\
|
||||||
else if(key == name) { \
|
else if(key == name) { \
|
||||||
if(!this->permission_granted(this->cached_permission_value(perm), 1)) return command_result{perm}; \
|
if(!this->permission_granted(this->calculate_permission(perm, 0), 1)) return command_result{perm}; \
|
||||||
if(toApplay.count(key) == 0) toApplay[key] = cmd[key].as<std::string>(); \
|
if(toApplay.count(key) == 0) toApplay[key] = cmd[key].as<std::string>(); \
|
||||||
if(!cmd[0][key].castable<type>()) return command_result{error::parameter_invalid};
|
if(!cmd[0][key].castable<type>()) return command_result{error::parameter_invalid};
|
||||||
|
|
||||||
#define SERVEREDIT_CHK_PROP2(name, perm, type_a, type_b)\
|
#define SERVEREDIT_CHK_PROP2(name, perm, type_a, type_b)\
|
||||||
else if(key == name) { \
|
else if(key == name) { \
|
||||||
if(!permissionGranted(permission::PERMTEST_HIGHEST, perm, 1, nullptr, true, cache, target_server, true)) return command_result{perm}; \
|
if(!permissionGranted(perm, 1, nullptr, true, cache, target_server, true)) return command_result{perm}; \
|
||||||
if(toApplay.count(key) == 0) toApplay[key] = cmd[key].as<std::string>(); \
|
if(toApplay.count(key) == 0) toApplay[key] = cmd[key].as<std::string>(); \
|
||||||
if(!cmd[0][key].castable<type_a>() && !!cmd[0][key].castable<type_b>()) return command_result{error::parameter_invalid};
|
if(!cmd[0][key].castable<type_a>() && !!cmd[0][key].castable<type_b>()) return command_result{error::parameter_invalid};
|
||||||
|
|
||||||
@ -619,11 +619,11 @@ command_result ConnectedClient::handleCommandClientKick(Command &cmd) {
|
|||||||
auto type = cmd["reasonid"].as<ViewReasonId>();
|
auto type = cmd["reasonid"].as<ViewReasonId>();
|
||||||
if (type == ViewReasonId::VREASON_CHANNEL_KICK) {
|
if (type == ViewReasonId::VREASON_CHANNEL_KICK) {
|
||||||
auto channel = client->currentChannel;
|
auto channel = client->currentChannel;
|
||||||
PERM_CHECK_CHANNELR(permission::i_client_kick_from_channel_power, client->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_needed_kick_from_channel_power, channel), channel, true);
|
PERM_CHECK_CHANNELR(permission::i_client_kick_from_channel_power, client->permissionValue(permission::i_client_needed_kick_from_channel_power, channel), channel, true);
|
||||||
targetChannel = this->server->channelTree->getDefaultChannel();
|
targetChannel = this->server->channelTree->getDefaultChannel();
|
||||||
} else if (type == ViewReasonId::VREASON_SERVER_KICK) {
|
} else if (type == ViewReasonId::VREASON_SERVER_KICK) {
|
||||||
auto channel = client->currentChannel;
|
auto channel = client->currentChannel;
|
||||||
PERM_CHECK_CHANNELR(permission::i_client_kick_from_server_power, client->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_needed_kick_from_server_power, channel), channel, true);
|
PERM_CHECK_CHANNELR(permission::i_client_kick_from_server_power, client->permissionValue(permission::i_client_needed_kick_from_server_power, channel), channel, true);
|
||||||
targetChannel = nullptr;
|
targetChannel = nullptr;
|
||||||
} else return command_result{error::not_implemented};
|
} else return command_result{error::not_implemented};
|
||||||
|
|
||||||
@ -643,7 +643,7 @@ command_result ConnectedClient::handleCommandChannelGetDescription(Command &cmd)
|
|||||||
auto channel = dynamic_pointer_cast<BasicChannel>(l_channel->entry);
|
auto channel = dynamic_pointer_cast<BasicChannel>(l_channel->entry);
|
||||||
assert(channel);
|
assert(channel);
|
||||||
|
|
||||||
if(!this->permission_granted(this->permissionValue(permission::b_channel_ignore_description_view_power, channel), 1, true)) {
|
if(!this->permission_granted(this->calculate_permission(permission::b_channel_ignore_description_view_power, channel->channelId()), 1, true)) {
|
||||||
CHANNEL_PERMISSION_TEST(permission::i_channel_description_view_power, permission::i_channel_needed_description_view_power, channel, false);
|
CHANNEL_PERMISSION_TEST(permission::i_channel_description_view_power, permission::i_channel_needed_description_view_power, channel, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -663,7 +663,7 @@ command_result ConnectedClient::handleCommandGetConnectionInfo(Command &cmd) {
|
|||||||
if (info) {
|
if (info) {
|
||||||
this->notifyConnectionInfo(client, info);
|
this->notifyConnectionInfo(client, info);
|
||||||
} else if(send_temp) {
|
} else if(send_temp) {
|
||||||
this->notifyConnectionInfo(client, nullptr);
|
return command_result{error::no_cached_connection_info};
|
||||||
}
|
}
|
||||||
|
|
||||||
return command_result{error::ok};
|
return command_result{error::ok};
|
||||||
@ -1034,7 +1034,7 @@ command_result ConnectedClient::handleCommandChannelGroupCopy(Command &cmd) {
|
|||||||
return command_result{result};
|
return command_result{result};
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!target_group->permission_granted(permission::i_channel_group_needed_modify_power, this->calculate_permission_value(permission::i_channel_group_modify_power, 0), true))
|
if(!target_group->permission_granted(permission::i_channel_group_needed_modify_power, this->calculate_permission(permission::i_channel_group_modify_power, 0), true))
|
||||||
return command_result{permission::i_channel_group_modify_power};
|
return command_result{permission::i_channel_group_modify_power};
|
||||||
|
|
||||||
if(!group_manager->copyGroupPermissions(source_group, target_group))
|
if(!group_manager->copyGroupPermissions(source_group, target_group))
|
||||||
@ -1230,7 +1230,7 @@ command_result ConnectedClient::handleCommandChannelGroupAddPerm(Command &cmd) {
|
|||||||
if (!channelGroup || channelGroup->target() != GROUPTARGET_CHANNEL) return command_result{error::parameter_invalid, "invalid channel group id"};
|
if (!channelGroup || channelGroup->target() != GROUPTARGET_CHANNEL) return command_result{error::parameter_invalid, "invalid channel group id"};
|
||||||
GROUP_PERMISSION_TEST(permission::i_channel_group_modify_power, permission::i_channel_group_needed_modify_power, channelGroup, true);
|
GROUP_PERMISSION_TEST(permission::i_channel_group_modify_power, permission::i_channel_group_needed_modify_power, channelGroup, true);
|
||||||
|
|
||||||
auto maxValue = this->getPermissionGrantValue(permission::PERMTEST_ORDERED, permission::i_permission_modify_power, this->currentChannel);
|
auto maxValue = this->getPermissionGrantValue(permission::i_permission_modify_power, this->currentChannel);
|
||||||
bool ignoreGrant = this->permission_granted(this->cached_permission_value(permission::b_permission_modify_power_ignore), 1);
|
bool ignoreGrant = this->permission_granted(this->cached_permission_value(permission::b_permission_modify_power_ignore), 1);
|
||||||
bool updateList = false;
|
bool updateList = false;
|
||||||
bool conOnError = cmd[0].has("continueonerror");
|
bool conOnError = cmd[0].has("continueonerror");
|
||||||
@ -1243,7 +1243,7 @@ command_result ConnectedClient::handleCommandChannelGroupAddPerm(Command &cmd) {
|
|||||||
if(permission_require_granted_value(permType) && val > maxValue)
|
if(permission_require_granted_value(permType) && val > maxValue)
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
|
|
||||||
if(!ignoreGrant && !this->permissionGrantGranted(permission::PERMTEST_ORDERED, permType, 1, this->currentChannel))
|
if(!ignoreGrant && !this->permissionGrantGranted(permType, 1, this->currentChannel))
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
|
|
||||||
if (grant) {
|
if (grant) {
|
||||||
@ -1299,7 +1299,7 @@ command_result ConnectedClient::handleCommandChannelGroupDelPerm(Command &cmd) {
|
|||||||
for (int index = 0; index < cmd.bulkCount(); index++) {
|
for (int index = 0; index < cmd.bulkCount(); index++) {
|
||||||
PARSE_PERMISSION(cmd)
|
PARSE_PERMISSION(cmd)
|
||||||
|
|
||||||
if(!ignoreGrant && !this->permissionGrantGranted(permission::PERMTEST_ORDERED, permType, 1, this->currentChannel))
|
if(!ignoreGrant && !this->permissionGrantGranted(permType, 1, this->currentChannel))
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
if (grant) {
|
if (grant) {
|
||||||
permission_manager->set_permission(permType, permission::v2::empty_permission_values, permission::v2::PermissionUpdateType::do_nothing, permission::v2::PermissionUpdateType::delete_value);
|
permission_manager->set_permission(permType, permission::v2::empty_permission_values, permission::v2::PermissionUpdateType::do_nothing, permission::v2::PermissionUpdateType::delete_value);
|
||||||
@ -1362,7 +1362,7 @@ command_result ConnectedClient::handleCommandClientMove(Command &cmd) {
|
|||||||
if(!cmd[0].has("cpw"))
|
if(!cmd[0].has("cpw"))
|
||||||
cmd["cpw"] = "";
|
cmd["cpw"] = "";
|
||||||
if (!channel->passwordMatch(cmd["cpw"], true))
|
if (!channel->passwordMatch(cmd["cpw"], true))
|
||||||
if (!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_channel_join_ignore_password, 1, channel, true, permission_cache))
|
if (!this->permissionGranted(permission::b_channel_join_ignore_password, 1, channel, true, permission_cache))
|
||||||
return command_result{error::channel_invalid_password};
|
return command_result{error::channel_invalid_password};
|
||||||
|
|
||||||
switch(channel->channelType()) {
|
switch(channel->channelType()) {
|
||||||
@ -1377,7 +1377,7 @@ command_result ConnectedClient::handleCommandClientMove(Command &cmd) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!channel->properties()[property::CHANNEL_FLAG_MAXCLIENTS_UNLIMITED].as<bool>() || !channel->properties()[property::CHANNEL_FLAG_MAXFAMILYCLIENTS_UNLIMITED].as<bool>()) {
|
if (!channel->properties()[property::CHANNEL_FLAG_MAXCLIENTS_UNLIMITED].as<bool>() || !channel->properties()[property::CHANNEL_FLAG_MAXFAMILYCLIENTS_UNLIMITED].as<bool>()) {
|
||||||
if(!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_channel_join_ignore_maxclients, 1, channel, true, permission_cache)) {
|
if(!this->permissionGranted(permission::b_channel_join_ignore_maxclients, 1, channel, true, permission_cache)) {
|
||||||
if(!channel->properties()[property::CHANNEL_FLAG_MAXCLIENTS_UNLIMITED].as<bool>()) {
|
if(!channel->properties()[property::CHANNEL_FLAG_MAXCLIENTS_UNLIMITED].as<bool>()) {
|
||||||
auto maxClients = channel->properties()[property::CHANNEL_MAXCLIENTS].as<int32_t>();
|
auto maxClients = channel->properties()[property::CHANNEL_MAXCLIENTS].as<int32_t>();
|
||||||
if (maxClients >= 0 && maxClients <= this->server->getClientsByChannel(channel).size())
|
if (maxClients >= 0 && maxClients <= this->server->getClientsByChannel(channel).size())
|
||||||
@ -1401,23 +1401,23 @@ command_result ConnectedClient::handleCommandClientMove(Command &cmd) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_channel_ignore_join_power, 1, channel, true, permission_cache)) {
|
if(!this->permissionGranted(permission::b_channel_ignore_join_power, 1, channel, true, permission_cache)) {
|
||||||
CHANNEL_PERMISSION_TEST(permission::i_channel_join_power, permission::i_channel_needed_join_power, channel, false);
|
CHANNEL_PERMISSION_TEST(permission::i_channel_join_power, permission::i_channel_needed_join_power, channel, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target_client == this) {
|
if (target_client == this) {
|
||||||
auto permission_cache_current = make_shared<CalculateCache>();
|
auto permission_cache_current = make_shared<CalculateCache>();
|
||||||
auto val = this->permissionValue(permission::PERMTEST_ORDERED, permission::b_client_is_sticky, this->currentChannel, permission_cache_current);
|
auto val = this->permissionValue(permission::b_client_is_sticky, this->currentChannel, permission_cache_current);
|
||||||
if (val != permNotGranted && val > 0) {
|
if (val != permNotGranted && val > 0) {
|
||||||
auto st = this->permissionValue(permission::PERMTEST_ORDERED, permission::b_client_ignore_sticky, this->currentChannel, permission_cache_current);
|
auto st = this->permissionValue(permission::b_client_ignore_sticky, this->currentChannel, permission_cache_current);
|
||||||
if (st != 1)
|
if (st != 1)
|
||||||
return command_result{permission::b_client_is_sticky};
|
return command_result{permission::b_client_is_sticky};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target_client != this) {
|
if (target_client != this) {
|
||||||
PERM_CHECK_CHANNELR(permission::i_client_move_power, target_client->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_needed_move_power, target_client->getChannel()), target_client->getChannel(), true);
|
PERM_CHECK_CHANNELR(permission::i_client_move_power, target_client->permissionValue(permission::i_client_needed_move_power, target_client->getChannel()), target_client->getChannel(), true);
|
||||||
PERM_CHECK_CHANNEL_CR(permission::i_client_move_power, target_client->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_needed_move_power, channel), channel, true, permission_cache);
|
PERM_CHECK_CHANNEL_CR(permission::i_client_move_power, target_client->permissionValue(permission::i_client_needed_move_power, channel), channel, true, permission_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
server_channel_r_lock.unlock();
|
server_channel_r_lock.unlock();
|
||||||
@ -1524,7 +1524,7 @@ command_result ConnectedClient::handleCommandChannelCreate(Command &cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
auto max_channels = this->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_max_channels, nullptr, permission_cache);
|
auto max_channels = this->permissionValue(permission::i_client_max_channels, nullptr, permission_cache);
|
||||||
|
|
||||||
if(max_channels >= 0) {
|
if(max_channels >= 0) {
|
||||||
if(max_channels <= created_perm + created_semi + created_tmp)
|
if(max_channels <= created_perm + created_semi + created_tmp)
|
||||||
@ -1532,21 +1532,21 @@ command_result ConnectedClient::handleCommandChannelCreate(Command &cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cmd[0]["channel_flag_permanent"].as<bool>()) {
|
if (cmd[0]["channel_flag_permanent"].as<bool>()) {
|
||||||
max_channels = this->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_max_permanent_channels, nullptr, permission_cache);
|
max_channels = this->permissionValue(permission::i_client_max_permanent_channels, nullptr, permission_cache);
|
||||||
if(max_channels >= 0) {
|
if(max_channels >= 0) {
|
||||||
if(max_channels <= created_perm)
|
if(max_channels <= created_perm)
|
||||||
return command_result{permission::i_client_max_permanent_channels};
|
return command_result{permission::i_client_max_permanent_channels};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (cmd[0]["channel_flag_semi_permanent"].as<bool>()) {
|
else if (cmd[0]["channel_flag_semi_permanent"].as<bool>()) {
|
||||||
max_channels = this->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_max_semi_channels, nullptr, permission_cache);
|
max_channels = this->permissionValue(permission::i_client_max_semi_channels, nullptr, permission_cache);
|
||||||
if(max_channels >= 0) {
|
if(max_channels >= 0) {
|
||||||
if(max_channels <= created_semi)
|
if(max_channels <= created_semi)
|
||||||
return command_result{permission::i_client_max_semi_channels};
|
return command_result{permission::i_client_max_semi_channels};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
max_channels = this->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_max_temporary_channels, nullptr, permission_cache);
|
max_channels = this->permissionValue(permission::i_client_max_temporary_channels, nullptr, permission_cache);
|
||||||
if(max_channels >= 0) {
|
if(max_channels >= 0) {
|
||||||
if(max_channels <= created_tmp)
|
if(max_channels <= created_tmp)
|
||||||
return command_result{permission::i_client_max_temporary_channels};
|
return command_result{permission::i_client_max_temporary_channels};
|
||||||
@ -1567,8 +1567,8 @@ command_result ConnectedClient::handleCommandChannelCreate(Command &cmd) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
auto min_channel_deep = this->permissionValue(permission::PERMTEST_ORDERED, permission::i_channel_min_depth, nullptr, permission_cache);
|
auto min_channel_deep = this->permissionValue(permission::i_channel_min_depth, nullptr, permission_cache);
|
||||||
auto max_channel_deep = this->permissionValue(permission::PERMTEST_ORDERED, permission::i_channel_max_depth, nullptr, permission_cache);
|
auto max_channel_deep = this->permissionValue(permission::i_channel_max_depth, nullptr, permission_cache);
|
||||||
|
|
||||||
if(min_channel_deep >= 0 || max_channel_deep >= 0) {
|
if(min_channel_deep >= 0 || max_channel_deep >= 0) {
|
||||||
auto channel_deep = 0;
|
auto channel_deep = 0;
|
||||||
@ -1622,13 +1622,13 @@ command_result ConnectedClient::handleCommandChannelCreate(Command &cmd) {
|
|||||||
auto permission_manager = created_channel->permissions();
|
auto permission_manager = created_channel->permissions();
|
||||||
permission_manager->set_permission(
|
permission_manager->set_permission(
|
||||||
permission::i_channel_needed_modify_power,
|
permission::i_channel_needed_modify_power,
|
||||||
{this->permissionValue(permission::PERMTEST_ORDERED, permission::i_channel_modify_power, this->currentChannel, permission_cache), 0},
|
{this->permissionValue(permission::i_channel_modify_power, this->currentChannel, permission_cache), 0},
|
||||||
permission::v2::PermissionUpdateType::set_value,
|
permission::v2::PermissionUpdateType::set_value,
|
||||||
permission::v2::PermissionUpdateType::do_nothing
|
permission::v2::PermissionUpdateType::do_nothing
|
||||||
);
|
);
|
||||||
permission_manager->set_permission(
|
permission_manager->set_permission(
|
||||||
permission::i_channel_needed_delete_power,
|
permission::i_channel_needed_delete_power,
|
||||||
{this->permissionValue(permission::PERMTEST_ORDERED, permission::i_channel_delete_power, this->currentChannel, permission_cache), 0},
|
{this->permissionValue(permission::i_channel_delete_power, this->currentChannel, permission_cache), 0},
|
||||||
permission::v2::PermissionUpdateType::set_value,
|
permission::v2::PermissionUpdateType::set_value,
|
||||||
permission::v2::PermissionUpdateType::do_nothing
|
permission::v2::PermissionUpdateType::do_nothing
|
||||||
);
|
);
|
||||||
@ -1849,13 +1849,13 @@ command_result ConnectedClient::handleCommandChannelEdit(Command &cmd) {
|
|||||||
CHANNEL_PERM_TEST(permission::b_channel_modify_topic, 1, true);
|
CHANNEL_PERM_TEST(permission::b_channel_modify_topic, 1, true);
|
||||||
} else if (key == "channel_description") {
|
} else if (key == "channel_description") {
|
||||||
CHANNEL_PERM_TEST(permission::b_channel_modify_description, 1, true);
|
CHANNEL_PERM_TEST(permission::b_channel_modify_description, 1, true);
|
||||||
if(!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_client_use_bbcode_any, 1, this->currentChannel)) {
|
if(!this->permissionGranted(permission::b_client_use_bbcode_any, 1, this->currentChannel)) {
|
||||||
auto bbcode_image = bbcode::sloppy::has_image(cmd[key]);
|
auto bbcode_image = bbcode::sloppy::has_image(cmd[key]);
|
||||||
auto bbcode_url = bbcode::sloppy::has_url(cmd[key]);
|
auto bbcode_url = bbcode::sloppy::has_url(cmd[key]);
|
||||||
debugMessage(this->getServerId(), "Channel description contains bb codes: Image: {} URL: {}", bbcode_image, bbcode_url);
|
debugMessage(this->getServerId(), "Channel description contains bb codes: Image: {} URL: {}", bbcode_image, bbcode_url);
|
||||||
if(bbcode_image && !this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_client_use_bbcode_image, 1, this->currentChannel))
|
if(bbcode_image && !this->permissionGranted(permission::b_client_use_bbcode_image, 1, this->currentChannel))
|
||||||
return command_result{permission::b_client_use_bbcode_image};
|
return command_result{permission::b_client_use_bbcode_image};
|
||||||
if(bbcode_url && !this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_client_use_bbcode_url, 1, this->currentChannel))
|
if(bbcode_url && !this->permissionGranted(permission::b_client_use_bbcode_url, 1, this->currentChannel))
|
||||||
return command_result{permission::b_client_use_bbcode_url};
|
return command_result{permission::b_client_use_bbcode_url};
|
||||||
}
|
}
|
||||||
} else if (key == "channel_codec") {
|
} else if (key == "channel_codec") {
|
||||||
@ -2270,8 +2270,8 @@ command_result ConnectedClient::handleCommandChannelMove(Command &cmd) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
auto min_channel_deep = this->permissionValue(permission::PERMTEST_ORDERED, permission::i_channel_min_depth, nullptr, nullptr);
|
auto min_channel_deep = this->permissionValue(permission::i_channel_min_depth, nullptr, nullptr);
|
||||||
auto max_channel_deep = this->permissionValue(permission::PERMTEST_ORDERED, permission::i_channel_max_depth, nullptr, nullptr);
|
auto max_channel_deep = this->permissionValue(permission::i_channel_max_depth, nullptr, nullptr);
|
||||||
|
|
||||||
if(min_channel_deep >= 0 || max_channel_deep >= 0) {
|
if(min_channel_deep >= 0 || max_channel_deep >= 0) {
|
||||||
auto channel_deep = 0;
|
auto channel_deep = 0;
|
||||||
@ -2355,7 +2355,7 @@ command_result ConnectedClient::handleCommandClientPoke(Command &cmd) {
|
|||||||
auto client = this->server->findClient(cmd["clid"].as<ClientId>());
|
auto client = this->server->findClient(cmd["clid"].as<ClientId>());
|
||||||
if (!client) return command_result{error::client_invalid_id};
|
if (!client) return command_result{error::client_invalid_id};
|
||||||
if (client->getType() == CLIENT_MUSIC) return command_result{error::client_invalid_type};
|
if (client->getType() == CLIENT_MUSIC) return command_result{error::client_invalid_type};
|
||||||
CACHED_PERM_CHECK(permission::i_client_poke_power, client->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_needed_poke_power, client->currentChannel), false);
|
CACHED_PERM_CHECK(permission::i_client_poke_power, client->permissionValue(permission::i_client_needed_poke_power, client->currentChannel), false);
|
||||||
|
|
||||||
client->notifyClientPoke(_this.lock(), cmd["msg"]);
|
client->notifyClientPoke(_this.lock(), cmd["msg"]);
|
||||||
return command_result{error::ok};
|
return command_result{error::ok};
|
||||||
@ -2432,8 +2432,8 @@ command_result ConnectedClient::handleCommandChannelAddPerm(Command &cmd) {
|
|||||||
|
|
||||||
CHANNEL_PERMISSION_TEST(permission::i_channel_permission_modify_power, permission::i_channel_needed_permission_modify_power, channel, true);
|
CHANNEL_PERMISSION_TEST(permission::i_channel_permission_modify_power, permission::i_channel_needed_permission_modify_power, channel, true);
|
||||||
|
|
||||||
auto maxValue = this->getPermissionGrantValue(permission::PERMTEST_ORDERED, permission::i_permission_modify_power, channel);
|
auto maxValue = this->getPermissionGrantValue(permission::i_permission_modify_power, channel);
|
||||||
bool ignoreGrant = this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_permission_modify_power_ignore, 1, channel);
|
bool ignoreGrant = this->permissionGranted(permission::b_permission_modify_power_ignore, 1, channel);
|
||||||
auto updateClients = false, update_view = false, update_channel_properties = false;
|
auto updateClients = false, update_view = false, update_channel_properties = false;
|
||||||
|
|
||||||
bool conOnError = cmd[0].has("continueonerror");
|
bool conOnError = cmd[0].has("continueonerror");
|
||||||
@ -2449,7 +2449,7 @@ command_result ConnectedClient::handleCommandChannelAddPerm(Command &cmd) {
|
|||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ignoreGrant && !this->permissionGrantGranted(permission::PERMTEST_ORDERED, permType, 1, channel)) {
|
if(!ignoreGrant && !this->permissionGrantGranted(permType, 1, channel)) {
|
||||||
if(conOnError) continue;
|
if(conOnError) continue;
|
||||||
|
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
@ -2536,7 +2536,7 @@ command_result ConnectedClient::handleCommandChannelDelPerm(Command &cmd) {
|
|||||||
assert(channel);
|
assert(channel);
|
||||||
CHANNEL_PERMISSION_TEST(permission::i_channel_permission_modify_power, permission::i_channel_needed_permission_modify_power, channel, true);
|
CHANNEL_PERMISSION_TEST(permission::i_channel_permission_modify_power, permission::i_channel_needed_permission_modify_power, channel, true);
|
||||||
|
|
||||||
bool ignoreGrant = this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_permission_modify_power_ignore, 1, channel);
|
bool ignoreGrant = this->permissionGranted(permission::b_permission_modify_power_ignore, 1, channel);
|
||||||
bool conOnError = cmd[0].has("continueonerror");
|
bool conOnError = cmd[0].has("continueonerror");
|
||||||
auto updateClients = false, update_view = false, update_channel_properties = false;
|
auto updateClients = false, update_view = false, update_channel_properties = false;
|
||||||
|
|
||||||
@ -2544,7 +2544,7 @@ command_result ConnectedClient::handleCommandChannelDelPerm(Command &cmd) {
|
|||||||
for (int index = 0; index < cmd.bulkCount(); index++) {
|
for (int index = 0; index < cmd.bulkCount(); index++) {
|
||||||
PARSE_PERMISSION(cmd);
|
PARSE_PERMISSION(cmd);
|
||||||
|
|
||||||
if(!ignoreGrant && !this->permissionGrantGranted(permission::PERMTEST_ORDERED, permType, 1, channel))
|
if(!ignoreGrant && !this->permissionGrantGranted(permType, 1, channel))
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
|
|
||||||
if (grant) {
|
if (grant) {
|
||||||
@ -2681,7 +2681,7 @@ command_result ConnectedClient::handleCommandServerGroupCopy(Command &cmd) {
|
|||||||
return command_result{result};
|
return command_result{result};
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!target_group->permission_granted(permission::i_server_group_needed_modify_power, this->calculate_permission_value(permission::i_server_group_modify_power, 0), true))
|
if(!target_group->permission_granted(permission::i_server_group_needed_modify_power, this->calculate_permission(permission::i_server_group_modify_power, 0), true))
|
||||||
return command_result{permission::i_server_group_modify_power};
|
return command_result{permission::i_server_group_modify_power};
|
||||||
|
|
||||||
if(!group_manager->copyGroupPermissions(source_group, target_group))
|
if(!group_manager->copyGroupPermissions(source_group, target_group))
|
||||||
@ -2836,7 +2836,7 @@ command_result ConnectedClient::handleCommandServerGroupAddClient(Command &cmd)
|
|||||||
auto target_cldbid = cmd["cldbid"].as<ClientDbId>();
|
auto target_cldbid = cmd["cldbid"].as<ClientDbId>();
|
||||||
if (!serverInstance->databaseHelper()->validClientDatabaseId(target_server, cmd["cldbid"])) return command_result{error::client_invalid_id, "invalid cldbid"};
|
if (!serverInstance->databaseHelper()->validClientDatabaseId(target_server, cmd["cldbid"])) return command_result{error::client_invalid_id, "invalid cldbid"};
|
||||||
|
|
||||||
auto needed_client_permission = this->server->calculatePermission(permission::PERMTEST_ORDERED, target_cldbid, permission::i_client_needed_permission_modify_power, ClientType::CLIENT_TEAMSPEAK, nullptr);
|
auto needed_client_permission = this->server->calculatePermission(target_cldbid, permission::i_client_needed_permission_modify_power, ClientType::CLIENT_TEAMSPEAK, nullptr);
|
||||||
if(needed_client_permission != permNotGranted) {
|
if(needed_client_permission != permNotGranted) {
|
||||||
if(!this->permission_granted(this->permissionValue(permission::i_client_permission_modify_power), needed_client_permission))
|
if(!this->permission_granted(this->permissionValue(permission::i_client_permission_modify_power), needed_client_permission))
|
||||||
return command_result{permission::i_client_needed_permission_modify_power};
|
return command_result{permission::i_client_needed_permission_modify_power};
|
||||||
@ -2848,8 +2848,8 @@ command_result ConnectedClient::handleCommandServerGroupAddClient(Command &cmd)
|
|||||||
|
|
||||||
auto continue_on_error = cmd.hasParm("continueonerror");
|
auto continue_on_error = cmd.hasParm("continueonerror");
|
||||||
{
|
{
|
||||||
auto permission_add_power = this->calculate_permission_value(permission::i_server_group_member_add_power, -1);
|
auto permission_add_power = this->calculate_permission(permission::i_server_group_member_add_power, -1);
|
||||||
auto permission_self_add_power = this->calculate_permission_value(permission::i_server_group_member_add_power, -1);
|
auto permission_self_add_power = this->calculate_permission(permission::i_server_group_member_add_power, -1);
|
||||||
|
|
||||||
for(auto index = 0; index < cmd.bulkCount(); index++) {
|
for(auto index = 0; index < cmd.bulkCount(); index++) {
|
||||||
auto group_id = cmd[index]["sgid"];
|
auto group_id = cmd[index]["sgid"];
|
||||||
@ -2952,7 +2952,7 @@ command_result ConnectedClient::handleCommandServerGroupDelClient(Command &cmd)
|
|||||||
auto target_cldbid = cmd["cldbid"].as<ClientDbId>();
|
auto target_cldbid = cmd["cldbid"].as<ClientDbId>();
|
||||||
if (!serverInstance->databaseHelper()->validClientDatabaseId(target_server, cmd["cldbid"])) return command_result{error::client_invalid_id, "invalid cldbid"};
|
if (!serverInstance->databaseHelper()->validClientDatabaseId(target_server, cmd["cldbid"])) return command_result{error::client_invalid_id, "invalid cldbid"};
|
||||||
|
|
||||||
auto needed_client_permission = this->server->calculatePermission(permission::PERMTEST_ORDERED, target_cldbid, permission::i_client_needed_permission_modify_power, ClientType::CLIENT_TEAMSPEAK, nullptr);
|
auto needed_client_permission = this->server->calculatePermission(target_cldbid, permission::i_client_needed_permission_modify_power, ClientType::CLIENT_TEAMSPEAK, nullptr);
|
||||||
if(needed_client_permission != permNotGranted) {
|
if(needed_client_permission != permNotGranted) {
|
||||||
if(!this->permission_granted(this->permissionValue(permission::i_client_permission_modify_power), needed_client_permission))
|
if(!this->permission_granted(this->permissionValue(permission::i_client_permission_modify_power), needed_client_permission))
|
||||||
return command_result{permission::i_client_needed_permission_modify_power};
|
return command_result{permission::i_client_needed_permission_modify_power};
|
||||||
@ -2964,8 +2964,8 @@ command_result ConnectedClient::handleCommandServerGroupDelClient(Command &cmd)
|
|||||||
|
|
||||||
auto continue_on_error = cmd.hasParm("continueonerror");
|
auto continue_on_error = cmd.hasParm("continueonerror");
|
||||||
{
|
{
|
||||||
auto permission_remove_power = this->calculate_permission_value(permission::i_server_group_member_remove_power, -1);
|
auto permission_remove_power = this->calculate_permission(permission::i_server_group_member_remove_power, -1);
|
||||||
auto permission_self_remove_power = this->calculate_permission_value(permission::i_server_group_member_remove_power, -1);
|
auto permission_self_remove_power = this->calculate_permission(permission::i_server_group_member_remove_power, -1);
|
||||||
|
|
||||||
for(auto index = 0; index < cmd.bulkCount(); index++) {
|
for(auto index = 0; index < cmd.bulkCount(); index++) {
|
||||||
auto group_id = cmd[index]["sgid"];
|
auto group_id = cmd[index]["sgid"];
|
||||||
@ -3104,7 +3104,7 @@ command_result ConnectedClient::handleCommandServerGroupAddPerm(Command &cmd) {
|
|||||||
return command_result{permission::b_serverinstance_modify_templates};
|
return command_result{permission::b_serverinstance_modify_templates};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto maxValue = this->getPermissionGrantValue(permission::PERMTEST_ORDERED, permission::i_permission_modify_power, this->currentChannel);
|
auto maxValue = this->getPermissionGrantValue(permission::i_permission_modify_power, this->currentChannel);
|
||||||
bool ignoreGrant = this->permission_granted(this->cached_permission_value(permission::b_permission_modify_power_ignore), 1);
|
bool ignoreGrant = this->permission_granted(this->cached_permission_value(permission::b_permission_modify_power_ignore), 1);
|
||||||
bool conOnError = cmd[0].has("continueonerror");
|
bool conOnError = cmd[0].has("continueonerror");
|
||||||
bool checkTp = false;
|
bool checkTp = false;
|
||||||
@ -3121,7 +3121,7 @@ command_result ConnectedClient::handleCommandServerGroupAddPerm(Command &cmd) {
|
|||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ignoreGrant && !this->permissionGrantGranted(permission::PERMTEST_ORDERED, permType, 1, this->currentChannel)) {
|
if(!ignoreGrant && !this->permissionGrantGranted(permType, 1, this->currentChannel)) {
|
||||||
if(conOnError) continue;
|
if(conOnError) continue;
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
}
|
}
|
||||||
@ -3194,7 +3194,7 @@ command_result ConnectedClient::handleCommandServerGroupDelPerm(Command &cmd) {
|
|||||||
for (int index = 0; index < cmd.bulkCount(); index++) {
|
for (int index = 0; index < cmd.bulkCount(); index++) {
|
||||||
PARSE_PERMISSION(cmd);
|
PARSE_PERMISSION(cmd);
|
||||||
|
|
||||||
if(!ignoreGrant && !this->permissionGrantGranted(permission::PERMTEST_ORDERED, permType, 1, this->currentChannel)) {
|
if(!ignoreGrant && !this->permissionGrantGranted(permType, 1, this->currentChannel)) {
|
||||||
if(conOnError) continue;
|
if(conOnError) continue;
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
}
|
}
|
||||||
@ -3250,13 +3250,13 @@ command_result ConnectedClient::handleCommandServerGroupAutoAddPerm(ts::Command&
|
|||||||
deque<shared_ptr<Group>> groups;
|
deque<shared_ptr<Group>> groups;
|
||||||
for(const auto& group : group_manager->availableGroups(false)) {
|
for(const auto& group : group_manager->availableGroups(false)) {
|
||||||
if(group->updateType() == cmd["sgtype"].as<permission::PermissionValue>() && group->target() == GROUPTARGET_SERVER) {
|
if(group->updateType() == cmd["sgtype"].as<permission::PermissionValue>() && group->target() == GROUPTARGET_SERVER) {
|
||||||
if(group->permission_granted(permission::i_server_group_needed_modify_power, this->calculate_permission_value(permission::i_server_group_modify_power, 0), true)) {
|
if(group->permission_granted(permission::i_server_group_needed_modify_power, this->calculate_permission(permission::i_server_group_modify_power, 0), true)) {
|
||||||
auto type = group->type();
|
auto type = group->type();
|
||||||
if(type == GroupType::GROUP_TYPE_QUERY) {
|
if(type == GroupType::GROUP_TYPE_QUERY) {
|
||||||
if(!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_serverinstance_modify_querygroup, 1))
|
if(!this->permissionGranted(permission::b_serverinstance_modify_querygroup, 1))
|
||||||
continue;
|
continue;
|
||||||
} else if(type == GroupType::GROUP_TYPE_TEMPLATE) {
|
} else if(type == GroupType::GROUP_TYPE_TEMPLATE) {
|
||||||
if(!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_serverinstance_modify_templates, 1))
|
if(!this->permissionGranted(permission::b_serverinstance_modify_templates, 1))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
groups.push_back(group);//sgtype
|
groups.push_back(group);//sgtype
|
||||||
@ -3267,9 +3267,9 @@ command_result ConnectedClient::handleCommandServerGroupAutoAddPerm(ts::Command&
|
|||||||
if(groups.empty())
|
if(groups.empty())
|
||||||
return command_result{error::ok};
|
return command_result{error::ok};
|
||||||
|
|
||||||
auto maxValue = this->getPermissionGrantValue(permission::PERMTEST_ORDERED, permission::i_permission_modify_power, this->currentChannel);
|
auto maxValue = this->getPermissionGrantValue(permission::i_permission_modify_power, this->currentChannel);
|
||||||
|
|
||||||
bool ignoreGrant = this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_permission_modify_power_ignore, 1);
|
bool ignoreGrant = this->permissionGranted(permission::b_permission_modify_power_ignore, 1);
|
||||||
bool conOnError = cmd[0].has("continueonerror");
|
bool conOnError = cmd[0].has("continueonerror");
|
||||||
bool checkTp = false;
|
bool checkTp = false;
|
||||||
bool sgroupUpdate = false;
|
bool sgroupUpdate = false;
|
||||||
@ -3284,7 +3284,7 @@ command_result ConnectedClient::handleCommandServerGroupAutoAddPerm(ts::Command&
|
|||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ignoreGrant && !this->permissionGrantGranted(permission::PERMTEST_ORDERED, permType, 1, this->currentChannel)) {
|
if(!ignoreGrant && !this->permissionGrantGranted(permType, 1, this->currentChannel)) {
|
||||||
if(conOnError) continue;
|
if(conOnError) continue;
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
}
|
}
|
||||||
@ -3347,13 +3347,13 @@ command_result ConnectedClient::handleCommandServerGroupAutoDelPerm(ts::Command&
|
|||||||
deque<shared_ptr<Group>> groups;
|
deque<shared_ptr<Group>> groups;
|
||||||
for(const auto& group : group_manager->availableGroups(false)) {
|
for(const auto& group : group_manager->availableGroups(false)) {
|
||||||
if(group->updateType() == cmd["sgtype"].as<permission::PermissionValue>() && group->target() == GROUPTARGET_SERVER) {
|
if(group->updateType() == cmd["sgtype"].as<permission::PermissionValue>() && group->target() == GROUPTARGET_SERVER) {
|
||||||
if(group->permission_granted(permission::i_server_group_needed_modify_power, this->calculate_permission_value(permission::i_server_group_modify_power, 0), true)) {
|
if(group->permission_granted(permission::i_server_group_needed_modify_power, this->calculate_permission(permission::i_server_group_modify_power, 0), true)) {
|
||||||
auto type = group->type();
|
auto type = group->type();
|
||||||
if(type == GroupType::GROUP_TYPE_QUERY) {
|
if(type == GroupType::GROUP_TYPE_QUERY) {
|
||||||
if(!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_serverinstance_modify_querygroup, 1))
|
if(!this->permissionGranted(permission::b_serverinstance_modify_querygroup, 1))
|
||||||
continue;
|
continue;
|
||||||
} else if(type == GroupType::GROUP_TYPE_TEMPLATE) {
|
} else if(type == GroupType::GROUP_TYPE_TEMPLATE) {
|
||||||
if(!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_serverinstance_modify_templates, 1))
|
if(!this->permissionGranted(permission::b_serverinstance_modify_templates, 1))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
groups.push_back(group);//sgtype
|
groups.push_back(group);//sgtype
|
||||||
@ -3363,14 +3363,14 @@ command_result ConnectedClient::handleCommandServerGroupAutoDelPerm(ts::Command&
|
|||||||
|
|
||||||
if(groups.empty()) return command_result{error::ok};
|
if(groups.empty()) return command_result{error::ok};
|
||||||
|
|
||||||
bool ignoreGrant = this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_permission_modify_power_ignore, 1);
|
bool ignoreGrant = this->permissionGranted(permission::b_permission_modify_power_ignore, 1);
|
||||||
bool conOnError = cmd[0].has("continueonerror");
|
bool conOnError = cmd[0].has("continueonerror");
|
||||||
bool checkTp = false;
|
bool checkTp = false;
|
||||||
auto sgroupUpdate = false;
|
auto sgroupUpdate = false;
|
||||||
for (int index = 0; index < cmd.bulkCount(); index++) {
|
for (int index = 0; index < cmd.bulkCount(); index++) {
|
||||||
PARSE_PERMISSION(cmd);
|
PARSE_PERMISSION(cmd);
|
||||||
|
|
||||||
if(!ignoreGrant && !this->permissionGrantGranted(permission::PERMTEST_ORDERED, permType, 1, this->currentChannel)) {
|
if(!ignoreGrant && !this->permissionGrantGranted(permType, 1, this->currentChannel)) {
|
||||||
if(conOnError) continue;
|
if(conOnError) continue;
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
}
|
}
|
||||||
@ -3441,18 +3441,18 @@ command_result ConnectedClient::handleCommandSetClientChannelGroup(Command &cmd)
|
|||||||
|
|
||||||
auto target_cldbid = cmd["cldbid"].as<ClientDbId>();
|
auto target_cldbid = cmd["cldbid"].as<ClientDbId>();
|
||||||
{
|
{
|
||||||
auto channel_group_member_add_power = this->calculate_permission_value(permission::i_channel_group_member_add_power, channel_id);
|
auto channel_group_member_add_power = this->calculate_permission(permission::i_channel_group_member_add_power, channel_id);
|
||||||
if(!serverGroup->permission_granted(permission::i_channel_group_needed_member_add_power, channel_group_member_add_power, true)) {
|
if(!serverGroup->permission_granted(permission::i_channel_group_needed_member_add_power, channel_group_member_add_power, true)) {
|
||||||
if(target_cldbid != this->getClientDatabaseId())
|
if(target_cldbid != this->getClientDatabaseId())
|
||||||
return command_result{permission::i_channel_group_member_add_power};
|
return command_result{permission::i_channel_group_member_add_power};
|
||||||
|
|
||||||
auto channel_group_self_add_power = this->calculate_permission_value(permission::i_channel_group_self_add_power, channel_id);
|
auto channel_group_self_add_power = this->calculate_permission(permission::i_channel_group_self_add_power, channel_id);
|
||||||
if(!serverGroup->permission_granted(permission::i_channel_group_needed_member_add_power, channel_group_self_add_power, true))
|
if(!serverGroup->permission_granted(permission::i_channel_group_needed_member_add_power, channel_group_self_add_power, true))
|
||||||
return command_result{permission::i_channel_group_self_add_power};
|
return command_result{permission::i_channel_group_self_add_power};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
auto client_permission_modify_power = this->calculate_permission_value(permission::i_client_permission_modify_power, channel_id);
|
auto client_permission_modify_power = this->calculate_permission(permission::i_client_permission_modify_power, channel_id);
|
||||||
auto client_needed_permission_modify_power = this->server->calculatePermission2(
|
auto client_needed_permission_modify_power = this->server->calculatePermission2(
|
||||||
permission::i_client_needed_permission_modify_power, target_cldbid, ClientType::CLIENT_TEAMSPEAK, channel_id);
|
permission::i_client_needed_permission_modify_power, target_cldbid, ClientType::CLIENT_TEAMSPEAK, channel_id);
|
||||||
|
|
||||||
@ -3466,12 +3466,12 @@ command_result ConnectedClient::handleCommandSetClientChannelGroup(Command &cmd)
|
|||||||
{
|
{
|
||||||
auto old_group = this->server->groups->getChannelGroupExact(target_cldbid, channel, false);
|
auto old_group = this->server->groups->getChannelGroupExact(target_cldbid, channel, false);
|
||||||
if(old_group) {
|
if(old_group) {
|
||||||
auto channel_group_member_remove_power = this->calculate_permission_value(permission::i_channel_group_member_remove_power, channel_id);
|
auto channel_group_member_remove_power = this->calculate_permission(permission::i_channel_group_member_remove_power, channel_id);
|
||||||
if(!serverGroup->permission_granted(permission::i_channel_group_needed_member_remove_power, channel_group_member_remove_power, true)) {
|
if(!serverGroup->permission_granted(permission::i_channel_group_needed_member_remove_power, channel_group_member_remove_power, true)) {
|
||||||
if(target_cldbid != this->getClientDatabaseId())
|
if(target_cldbid != this->getClientDatabaseId())
|
||||||
return command_result{permission::i_channel_group_member_remove_power};
|
return command_result{permission::i_channel_group_member_remove_power};
|
||||||
|
|
||||||
auto channel_group_self_remove_power = this->calculate_permission_value(permission::i_channel_group_self_remove_power, channel_id);
|
auto channel_group_self_remove_power = this->calculate_permission(permission::i_channel_group_self_remove_power, channel_id);
|
||||||
if(!serverGroup->permission_granted(permission::i_channel_group_needed_member_remove_power, channel_group_self_remove_power, true))
|
if(!serverGroup->permission_granted(permission::i_channel_group_needed_member_remove_power, channel_group_self_remove_power, true))
|
||||||
return command_result{permission::i_channel_group_self_remove_power};
|
return command_result{permission::i_channel_group_self_remove_power};
|
||||||
}
|
}
|
||||||
@ -3534,7 +3534,7 @@ command_result ConnectedClient::handleCommandSendTextMessage(Command &cmd) {
|
|||||||
PERM_CHECK_CHANNELR(permission::b_client_even_textmessage_send, 1, this->currentChannel, true);
|
PERM_CHECK_CHANNELR(permission::b_client_even_textmessage_send, 1, this->currentChannel, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
PERM_CHECK_CHANNELR(permission::i_client_private_textmessage_power, target->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_needed_private_textmessage_power, target->currentChannel), this->currentChannel, false);
|
PERM_CHECK_CHANNELR(permission::i_client_private_textmessage_power, target->permissionValue(permission::i_client_needed_private_textmessage_power, target->currentChannel), this->currentChannel, false);
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -3568,7 +3568,7 @@ command_result ConnectedClient::handleCommandSendTextMessage(Command &cmd) {
|
|||||||
channel_tree_read_lock.lock();
|
channel_tree_read_lock.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_client_channel_textmessage_send, 1, channel, false))
|
if(!this->permissionGranted(permission::b_client_channel_textmessage_send, 1, channel, false))
|
||||||
return command_result{permission::b_client_channel_textmessage_send};
|
return command_result{permission::b_client_channel_textmessage_send};
|
||||||
|
|
||||||
bool conversation_private = channel->properties()[property::CHANNEL_FLAG_CONVERSATION_PRIVATE].as<bool>();
|
bool conversation_private = channel->properties()[property::CHANNEL_FLAG_CONVERSATION_PRIVATE].as<bool>();
|
||||||
@ -3715,7 +3715,7 @@ command_result ConnectedClient::handleCommandFTGetFileList(Command &cmd) {
|
|||||||
if (cmd[0].has("cid") && cmd["cid"] != 0) { //Channel
|
if (cmd[0].has("cid") && cmd["cid"] != 0) { //Channel
|
||||||
auto channel = this->server->channelTree->findChannel(cmd["cid"].as<ChannelId>());
|
auto channel = this->server->channelTree->findChannel(cmd["cid"].as<ChannelId>());
|
||||||
if (!channel) return command_result{error::channel_invalid_id, "Cant resolve channel"};
|
if (!channel) return command_result{error::channel_invalid_id, "Cant resolve channel"};
|
||||||
if (!channel->passwordMatch(cmd["cpw"]) && !this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_ft_ignore_password, 1, channel, true))
|
if (!channel->passwordMatch(cmd["cpw"]) && !this->permissionGranted(permission::b_ft_ignore_password, 1, channel, true))
|
||||||
return cmd["cpw"].string().empty() ? command_result{permission::b_ft_ignore_password} : command_result{error::channel_invalid_password};
|
return cmd["cpw"].string().empty() ? command_result{permission::b_ft_ignore_password} : command_result{error::channel_invalid_password};
|
||||||
CHANNEL_PERMISSION_TEST(permission::i_ft_file_browse_power, permission::i_ft_needed_file_browse_power, channel, true);
|
CHANNEL_PERMISSION_TEST(permission::i_ft_file_browse_power, permission::i_ft_needed_file_browse_power, channel, true);
|
||||||
cmd_filelist_append_files(
|
cmd_filelist_append_files(
|
||||||
@ -3759,7 +3759,7 @@ command_result ConnectedClient::handleCommandFTCreateDir(Command &cmd) {
|
|||||||
|
|
||||||
auto channel = this->server->channelTree->findChannel(cmd["cid"].as<ChannelId>());
|
auto channel = this->server->channelTree->findChannel(cmd["cid"].as<ChannelId>());
|
||||||
if (!channel) return command_result{error::channel_invalid_id, "Cant resolve channel"};
|
if (!channel) return command_result{error::channel_invalid_id, "Cant resolve channel"};
|
||||||
if (!channel->passwordMatch(cmd["cpw"]) && !this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_ft_ignore_password, 1, channel, true))
|
if (!channel->passwordMatch(cmd["cpw"]) && !this->permissionGranted(permission::b_ft_ignore_password, 1, channel, true))
|
||||||
return cmd["cpw"].string().empty() ? command_result{permission::b_ft_ignore_password} : command_result{error::channel_invalid_password};
|
return cmd["cpw"].string().empty() ? command_result{permission::b_ft_ignore_password} : command_result{error::channel_invalid_password};
|
||||||
CHANNEL_PERMISSION_TEST(permission::i_ft_directory_create_power, permission::i_ft_needed_directory_create_power, channel, true);
|
CHANNEL_PERMISSION_TEST(permission::i_ft_directory_create_power, permission::i_ft_needed_directory_create_power, channel, true);
|
||||||
|
|
||||||
@ -3780,7 +3780,7 @@ command_result ConnectedClient::handleCommandFTDeleteFile(Command &cmd) {
|
|||||||
if (cmd[0].has("cid") && cmd["cid"] != 0) { //Channel
|
if (cmd[0].has("cid") && cmd["cid"] != 0) { //Channel
|
||||||
auto channel = this->server->channelTree->findChannel(cmd["cid"].as<ChannelId>());
|
auto channel = this->server->channelTree->findChannel(cmd["cid"].as<ChannelId>());
|
||||||
if (!channel) return command_result{error::channel_invalid_id, "Cant resolve channel"};
|
if (!channel) return command_result{error::channel_invalid_id, "Cant resolve channel"};
|
||||||
if (!channel->passwordMatch(cmd["cpw"]) && !this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_ft_ignore_password, 1, channel, true))
|
if (!channel->passwordMatch(cmd["cpw"]) && !this->permissionGranted(permission::b_ft_ignore_password, 1, channel, true))
|
||||||
return cmd["cpw"].string().empty() ? command_result{permission::b_ft_ignore_password} : command_result{error::channel_invalid_password};
|
return cmd["cpw"].string().empty() ? command_result{permission::b_ft_ignore_password} : command_result{error::channel_invalid_password};
|
||||||
CHANNEL_PERMISSION_TEST(permission::i_ft_file_delete_power, permission::i_ft_needed_file_delete_power, channel, true);
|
CHANNEL_PERMISSION_TEST(permission::i_ft_file_delete_power, permission::i_ft_needed_file_delete_power, channel, true);
|
||||||
for (int index = 0; index < cmd.bulkCount(); index++)
|
for (int index = 0; index < cmd.bulkCount(); index++)
|
||||||
@ -3834,17 +3834,17 @@ command_result ConnectedClient::handleCommandFTInitUpload(Command &cmd) {
|
|||||||
if (cmd[0].has("cid") && cmd["cid"] != 0) { //Channel
|
if (cmd[0].has("cid") && cmd["cid"] != 0) { //Channel
|
||||||
auto channel = this->server->channelTree->findChannel(cmd["cid"].as<ChannelId>());
|
auto channel = this->server->channelTree->findChannel(cmd["cid"].as<ChannelId>());
|
||||||
if (!channel) return command_result{error::channel_invalid_id, "Cant resolve channel"};
|
if (!channel) return command_result{error::channel_invalid_id, "Cant resolve channel"};
|
||||||
if (!channel->passwordMatch(cmd["cpw"]) && !this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_ft_ignore_password, 1, channel, true))
|
if (!channel->passwordMatch(cmd["cpw"]) && !this->permissionGranted(permission::b_ft_ignore_password, 1, channel, true))
|
||||||
return cmd["cpw"].string().empty() ? command_result{permission::b_ft_ignore_password} : command_result{error::channel_invalid_password};
|
return cmd["cpw"].string().empty() ? command_result{permission::b_ft_ignore_password} : command_result{error::channel_invalid_password};
|
||||||
CHANNEL_PERMISSION_TEST(permission::i_ft_file_upload_power, permission::i_ft_needed_file_upload_power, channel, true);
|
CHANNEL_PERMISSION_TEST(permission::i_ft_file_upload_power, permission::i_ft_needed_file_upload_power, channel, true);
|
||||||
directory = serverInstance->getFileServer()->resolveDirectory(this->server, channel);
|
directory = serverInstance->getFileServer()->resolveDirectory(this->server, channel);
|
||||||
} else {
|
} else {
|
||||||
if (cmd["path"].as<std::string>().empty() && cmd["name"].as<std::string>().find("/icon_") == 0) {
|
if (cmd["path"].as<std::string>().empty() && cmd["name"].as<std::string>().find("/icon_") == 0) {
|
||||||
auto max_size = this->permissionValue(permission::PERMTEST_ORDERED, permission::i_max_icon_filesize, this->currentChannel);
|
auto max_size = this->permissionValue(permission::i_max_icon_filesize, this->currentChannel);
|
||||||
if(max_size != -1 && max_size < (ssize_t) cmd["size"].as<size_t>()) return command_result{permission::i_max_icon_filesize};
|
if(max_size != -1 && max_size < (ssize_t) cmd["size"].as<size_t>()) return command_result{permission::i_max_icon_filesize};
|
||||||
directory = serverInstance->getFileServer()->iconDirectory(this->server);
|
directory = serverInstance->getFileServer()->iconDirectory(this->server);
|
||||||
} else if (cmd["path"].as<std::string>().empty() && cmd["name"].string() == "/avatar") {
|
} else if (cmd["path"].as<std::string>().empty() && cmd["name"].string() == "/avatar") {
|
||||||
auto max_size = this->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_max_avatar_filesize, this->currentChannel);
|
auto max_size = this->permissionValue(permission::i_client_max_avatar_filesize, this->currentChannel);
|
||||||
if(max_size != -1 && max_size < (ssize_t) cmd["size"].as<size_t>()) return command_result{permission::i_client_max_avatar_filesize};
|
if(max_size != -1 && max_size < (ssize_t) cmd["size"].as<size_t>()) return command_result{permission::i_client_max_avatar_filesize};
|
||||||
|
|
||||||
directory = serverInstance->getFileServer()->avatarDirectory(this->server);
|
directory = serverInstance->getFileServer()->avatarDirectory(this->server);
|
||||||
@ -3870,7 +3870,7 @@ command_result ConnectedClient::handleCommandFTInitUpload(Command &cmd) {
|
|||||||
server_used_quota += trans->remaining_bytes();
|
server_used_quota += trans->remaining_bytes();
|
||||||
if(server_quota >= 0 && server_quota * 1024 * 1024 < (int64_t) server_used_quota) return command_result{error::file_transfer_server_quota_exceeded};
|
if(server_quota >= 0 && server_quota * 1024 * 1024 < (int64_t) server_used_quota) return command_result{error::file_transfer_server_quota_exceeded};
|
||||||
|
|
||||||
auto client_quota = this->permissionValue(permission::PERMTEST_ORDERED, permission::i_ft_quota_mb_upload_per_client, this->currentChannel);
|
auto client_quota = this->permissionValue(permission::i_ft_quota_mb_upload_per_client, this->currentChannel);
|
||||||
auto client_used_quota = this->properties()[property::CLIENT_MONTH_BYTES_UPLOADED].as<size_t>();
|
auto client_used_quota = this->properties()[property::CLIENT_MONTH_BYTES_UPLOADED].as<size_t>();
|
||||||
client_used_quota += cmd["size"].as<uint64_t>();
|
client_used_quota += cmd["size"].as<uint64_t>();
|
||||||
for(const auto& trans : serverInstance->getFileServer()->pending_file_transfers(_this.lock()))
|
for(const auto& trans : serverInstance->getFileServer()->pending_file_transfers(_this.lock()))
|
||||||
@ -3932,7 +3932,7 @@ command_result ConnectedClient::handleCommandFTInitDownload(Command &cmd) {
|
|||||||
if (!channel) return command_result{error::channel_invalid_id, "Cant resolve channel"};
|
if (!channel) return command_result{error::channel_invalid_id, "Cant resolve channel"};
|
||||||
|
|
||||||
CHANNEL_PERMISSION_TEST(permission::i_ft_file_download_power, permission::i_ft_needed_file_download_power, channel, true);
|
CHANNEL_PERMISSION_TEST(permission::i_ft_file_download_power, permission::i_ft_needed_file_download_power, channel, true);
|
||||||
if (!channel->passwordMatch(cmd["cpw"]) && !this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_ft_ignore_password, 1, channel, true))
|
if (!channel->passwordMatch(cmd["cpw"]) && !this->permissionGranted(permission::b_ft_ignore_password, 1, channel, true))
|
||||||
return cmd["cpw"].string().empty() ? command_result{permission::b_ft_ignore_password} : command_result{error::channel_invalid_password};
|
return cmd["cpw"].string().empty() ? command_result{permission::b_ft_ignore_password} : command_result{error::channel_invalid_password};
|
||||||
|
|
||||||
directory = serverInstance->getFileServer()->resolveDirectory(this->server, channel);
|
directory = serverInstance->getFileServer()->resolveDirectory(this->server, channel);
|
||||||
@ -3970,7 +3970,7 @@ command_result ConnectedClient::handleCommandFTInitDownload(Command &cmd) {
|
|||||||
if(server_quota >= 0 && server_quota * 1024 * 1024 < (int64_t) server_used_quota) return command_result{error::file_transfer_server_quota_exceeded};
|
if(server_quota >= 0 && server_quota * 1024 * 1024 < (int64_t) server_used_quota) return command_result{error::file_transfer_server_quota_exceeded};
|
||||||
|
|
||||||
|
|
||||||
auto client_quota = this->permissionValue(permission::PERMTEST_ORDERED, permission::i_ft_quota_mb_download_per_client, this->currentChannel);
|
auto client_quota = this->permissionValue(permission::i_ft_quota_mb_download_per_client, this->currentChannel);
|
||||||
auto client_used_quota = this->properties()[property::CLIENT_MONTH_BYTES_DOWNLOADED].as<size_t>();
|
auto client_used_quota = this->properties()[property::CLIENT_MONTH_BYTES_DOWNLOADED].as<size_t>();
|
||||||
client_used_quota += key->size;
|
client_used_quota += key->size;
|
||||||
for(const auto& trans : serverInstance->getFileServer()->pending_file_transfers(_this.lock()))
|
for(const auto& trans : serverInstance->getFileServer()->pending_file_transfers(_this.lock()))
|
||||||
@ -4042,7 +4042,7 @@ command_result ConnectedClient::handleCommandFTGetFileInfo(ts::Command &cmd) {
|
|||||||
if (request.has("cid") && request["cid"].as<ChannelId>() != 0) { //Channel
|
if (request.has("cid") && request["cid"].as<ChannelId>() != 0) { //Channel
|
||||||
auto channel = this->server->channelTree->findChannel(request["cid"].as<ChannelId>());
|
auto channel = this->server->channelTree->findChannel(request["cid"].as<ChannelId>());
|
||||||
if (!channel) return command_result{error::channel_invalid_id, "Cant resolve channel"};
|
if (!channel) return command_result{error::channel_invalid_id, "Cant resolve channel"};
|
||||||
if (!channel->passwordMatch(cmd["cpw"]) && !this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_ft_ignore_password, 1, channel, true))
|
if (!channel->passwordMatch(cmd["cpw"]) && !this->permissionGranted(permission::b_ft_ignore_password, 1, channel, true))
|
||||||
return cmd["cpw"].string().empty() ? command_result{permission::b_ft_ignore_password} : command_result{error::channel_invalid_password};
|
return cmd["cpw"].string().empty() ? command_result{permission::b_ft_ignore_password} : command_result{error::channel_invalid_password};
|
||||||
|
|
||||||
CHANNEL_PERMISSION_TEST(permission::i_ft_file_browse_power, permission::i_ft_needed_file_browse_power, channel, true);
|
CHANNEL_PERMISSION_TEST(permission::i_ft_file_browse_power, permission::i_ft_needed_file_browse_power, channel, true);
|
||||||
@ -4097,7 +4097,7 @@ command_result ConnectedClient::handleCommandBanList(Command &cmd) {
|
|||||||
auto server = serverInstance->getVoiceServerManager()->findServerById(sid);
|
auto server = serverInstance->getVoiceServerManager()->findServerById(sid);
|
||||||
if (!server) return command_result{error::parameter_invalid};
|
if (!server) return command_result{error::parameter_invalid};
|
||||||
|
|
||||||
if (server->calculatePermission(permission::PERMTEST_ORDERED, this->getClientDatabaseId(), permission::b_client_ban_list, this->getType(), nullptr) != 1)
|
if (server->calculatePermission(this->getClientDatabaseId(), permission::b_client_ban_list, this->getType(), nullptr) != 1)
|
||||||
return command_result{permission::b_client_ban_list};
|
return command_result{permission::b_client_ban_list};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4159,7 +4159,7 @@ command_result ConnectedClient::handleCommandBanAdd(Command &cmd) {
|
|||||||
} else {
|
} else {
|
||||||
auto server = serverInstance->getVoiceServerManager()->findServerById(sid);
|
auto server = serverInstance->getVoiceServerManager()->findServerById(sid);
|
||||||
if (!server) return command_result{error::parameter_invalid};
|
if (!server) return command_result{error::parameter_invalid};
|
||||||
if (server->calculatePermission(permission::PERMTEST_ORDERED, this->getClientDatabaseId(), permission::b_client_ban_create, this->getType(), nullptr) != 1)
|
if (server->calculatePermission(this->getClientDatabaseId(), permission::b_client_ban_create, this->getType(), nullptr) != 1)
|
||||||
return command_result{permission::b_client_ban_create_global};
|
return command_result{permission::b_client_ban_create_global};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4210,7 +4210,7 @@ command_result ConnectedClient::handleCommandBanEdit(Command &cmd) {
|
|||||||
auto server = serverInstance->getVoiceServerManager()->findServerById(sid);
|
auto server = serverInstance->getVoiceServerManager()->findServerById(sid);
|
||||||
if (!server) return command_result{error::parameter_invalid};
|
if (!server) return command_result{error::parameter_invalid};
|
||||||
|
|
||||||
if (server->calculatePermission(permission::PERMTEST_ORDERED, this->getClientDatabaseId(), permission::b_client_ban_edit, this->getType(), nullptr) != 1) return command_result{permission::b_client_ban_edit};
|
if (server->calculatePermission(this->getClientDatabaseId(), permission::b_client_ban_edit, this->getType(), nullptr) != 1) return command_result{permission::b_client_ban_edit};
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ip name uid reason time hwid */
|
/* ip name uid reason time hwid */
|
||||||
@ -4298,9 +4298,9 @@ command_result ConnectedClient::handleCommandBanClient(Command &cmd) {
|
|||||||
return command_result{error::client_unknown};
|
return command_result{error::client_unknown};
|
||||||
}
|
}
|
||||||
if (target_dbid != 0) {
|
if (target_dbid != 0) {
|
||||||
if (this->server->calculatePermission(permission::PERMTEST_ORDERED, target_dbid, permission::i_client_needed_ban_power, ClientType::CLIENT_TEAMSPEAK, nullptr) > this->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_ban_power))
|
if (this->server->calculatePermission(target_dbid, permission::i_client_needed_ban_power, ClientType::CLIENT_TEAMSPEAK, nullptr) > this->permissionValue(permission::i_client_ban_power))
|
||||||
return command_result{permission::i_client_ban_power};
|
return command_result{permission::i_client_ban_power};
|
||||||
if (this->server->calculatePermission(permission::PERMTEST_ORDERED, target_dbid, permission::b_client_ignore_bans, ClientType::CLIENT_TEAMSPEAK, nullptr) >= 1) return command_result{permission::b_client_ignore_bans};
|
if (this->server->calculatePermission(target_dbid, permission::b_client_ignore_bans, ClientType::CLIENT_TEAMSPEAK, nullptr) >= 1) return command_result{permission::b_client_ignore_bans};
|
||||||
}
|
}
|
||||||
deque<BanId> ban_ids;
|
deque<BanId> ban_ids;
|
||||||
auto _id = serverInstance->banManager()->registerBan(this->getServer()->getServerId(), this->getClientDatabaseId(), reason, uid, "", "", "", until);
|
auto _id = serverInstance->banManager()->registerBan(this->getServer()->getServerId(), this->getClientDatabaseId(), reason, uid, "", "", "", until);
|
||||||
@ -4376,7 +4376,7 @@ command_result ConnectedClient::handleCommandBanDel(Command &cmd) {
|
|||||||
if (!server) return command_result{error::parameter_invalid};
|
if (!server) return command_result{error::parameter_invalid};
|
||||||
|
|
||||||
auto perm = ban->invokerDbId == this->getClientDatabaseId() ? permission::b_client_ban_delete_own : permission::b_client_ban_delete;
|
auto perm = ban->invokerDbId == this->getClientDatabaseId() ? permission::b_client_ban_delete_own : permission::b_client_ban_delete;
|
||||||
if (server->calculatePermission(permission::PERMTEST_ORDERED, this->getClientDatabaseId(), perm, this->getType(), nullptr) != 1) return command_result{perm};
|
if (server->calculatePermission(this->getClientDatabaseId(), perm, this->getType(), nullptr) != 1) return command_result{perm};
|
||||||
}
|
}
|
||||||
serverInstance->banManager()->unban(ban);
|
serverInstance->banManager()->unban(ban);
|
||||||
return command_result{error::ok};
|
return command_result{error::ok};
|
||||||
@ -4763,7 +4763,7 @@ command_result ConnectedClient::handleCommandClientEdit(Command &cmd, const std:
|
|||||||
PERM_CHECKR(permission::b_client_modify_own_description, 1, true);
|
PERM_CHECKR(permission::b_client_modify_own_description, 1, true);
|
||||||
else if(client->getType() == ClientType::CLIENT_MUSIC) {
|
else if(client->getType() == ClientType::CLIENT_MUSIC) {
|
||||||
if(client->properties()[property::CLIENT_OWNER] != this->getClientDatabaseId()) {
|
if(client->properties()[property::CLIENT_OWNER] != this->getClientDatabaseId()) {
|
||||||
CACHED_PERM_CHECK(permission::i_client_music_modify_power, client->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_music_needed_modify_power, client->currentChannel), true);
|
CACHED_PERM_CHECK(permission::i_client_music_modify_power, client->permissionValue(permission::i_client_music_needed_modify_power, client->currentChannel), true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PERM_CHECKR(permission::b_client_modify_description, 1, true);
|
PERM_CHECKR(permission::b_client_modify_description, 1, true);
|
||||||
@ -4784,7 +4784,7 @@ command_result ConnectedClient::handleCommandClientEdit(Command &cmd, const std:
|
|||||||
if(!self) {
|
if(!self) {
|
||||||
if(client->getType() != ClientType::CLIENT_MUSIC) return command_result{error::client_invalid_type};
|
if(client->getType() != ClientType::CLIENT_MUSIC) return command_result{error::client_invalid_type};
|
||||||
if(client->properties()[property::CLIENT_OWNER] != this->getClientDatabaseId()) {
|
if(client->properties()[property::CLIENT_OWNER] != this->getClientDatabaseId()) {
|
||||||
CACHED_PERM_CHECK(permission::i_client_music_rename_power, client->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_music_needed_rename_power, client->currentChannel), true);
|
CACHED_PERM_CHECK(permission::i_client_music_rename_power, client->permissionValue(permission::i_client_music_needed_rename_power, client->currentChannel), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4792,7 +4792,7 @@ command_result ConnectedClient::handleCommandClientEdit(Command &cmd, const std:
|
|||||||
if (count_characters(name) < 3) return command_result{error::parameter_invalid, "Invalid name length. A minimum of 3 characters is required!"};
|
if (count_characters(name) < 3) return command_result{error::parameter_invalid, "Invalid name length. A minimum of 3 characters is required!"};
|
||||||
if (count_characters(name) > 30) return command_result{error::parameter_invalid, "Invalid name length. A maximum of 30 characters is allowed!"};
|
if (count_characters(name) > 30) return command_result{error::parameter_invalid, "Invalid name length. A maximum of 30 characters is allowed!"};
|
||||||
|
|
||||||
auto banIgnore = this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_client_ignore_bans, 1, this->currentChannel);
|
auto banIgnore = this->permissionGranted(permission::b_client_ignore_bans, 1, this->currentChannel);
|
||||||
if (!banIgnore) {
|
if (!banIgnore) {
|
||||||
auto banRecord = serverInstance->banManager()->findBanByName(this->getServerId(), name);
|
auto banRecord = serverInstance->banManager()->findBanByName(this->getServerId(), name);
|
||||||
if (banRecord)
|
if (banRecord)
|
||||||
@ -4817,7 +4817,7 @@ command_result ConnectedClient::handleCommandClientEdit(Command &cmd, const std:
|
|||||||
} else if(*info == property::CLIENT_PLAYER_VOLUME) {
|
} else if(*info == property::CLIENT_PLAYER_VOLUME) {
|
||||||
if(client->getType() != ClientType::CLIENT_MUSIC) return command_result{error::client_invalid_type};
|
if(client->getType() != ClientType::CLIENT_MUSIC) return command_result{error::client_invalid_type};
|
||||||
if(client->properties()[property::CLIENT_OWNER] != this->getClientDatabaseId()) {
|
if(client->properties()[property::CLIENT_OWNER] != this->getClientDatabaseId()) {
|
||||||
CACHED_PERM_CHECK(permission::i_client_music_modify_power, client->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_music_needed_modify_power, client->currentChannel), true);
|
CACHED_PERM_CHECK(permission::i_client_music_modify_power, client->permissionValue(permission::i_client_music_needed_modify_power, client->currentChannel), true);
|
||||||
}
|
}
|
||||||
auto bot = dynamic_pointer_cast<MusicClient>(client);
|
auto bot = dynamic_pointer_cast<MusicClient>(client);
|
||||||
assert(bot);
|
assert(bot);
|
||||||
@ -4831,7 +4831,7 @@ command_result ConnectedClient::handleCommandClientEdit(Command &cmd, const std:
|
|||||||
if(!self) {
|
if(!self) {
|
||||||
if(client->getType() != ClientType::CLIENT_MUSIC) return command_result{error::client_invalid_type};
|
if(client->getType() != ClientType::CLIENT_MUSIC) return command_result{error::client_invalid_type};
|
||||||
if(client->properties()[property::CLIENT_OWNER] != this->getClientDatabaseId()) {
|
if(client->properties()[property::CLIENT_OWNER] != this->getClientDatabaseId()) {
|
||||||
CACHED_PERM_CHECK(permission::i_client_music_modify_power, client->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_music_needed_modify_power, client->currentChannel), true);
|
CACHED_PERM_CHECK(permission::i_client_music_modify_power, client->permissionValue(permission::i_client_music_needed_modify_power, client->currentChannel), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4844,7 +4844,7 @@ command_result ConnectedClient::handleCommandClientEdit(Command &cmd, const std:
|
|||||||
if(client->getType() != ClientType::CLIENT_MUSIC)
|
if(client->getType() != ClientType::CLIENT_MUSIC)
|
||||||
return command_result{error::client_invalid_type};
|
return command_result{error::client_invalid_type};
|
||||||
if(client->properties()[property::CLIENT_OWNER] != this->getClientDatabaseId()) {
|
if(client->properties()[property::CLIENT_OWNER] != this->getClientDatabaseId()) {
|
||||||
CACHED_PERM_CHECK(permission::i_client_music_modify_power, client->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_music_needed_modify_power, client->currentChannel), true);
|
CACHED_PERM_CHECK(permission::i_client_music_modify_power, client->permissionValue(permission::i_client_music_needed_modify_power, client->currentChannel), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4871,7 +4871,7 @@ command_result ConnectedClient::handleCommandClientEdit(Command &cmd, const std:
|
|||||||
index++;
|
index++;
|
||||||
} while (index < str.length() && index != 0);
|
} while (index < str.length() && index != 0);
|
||||||
if (badgesTags >= 2) {
|
if (badgesTags >= 2) {
|
||||||
if (!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_client_allow_invalid_badges, 1, this->currentChannel))
|
if (!this->permissionGranted(permission::b_client_allow_invalid_badges, 1, this->currentChannel))
|
||||||
((VoiceClient *) this)->disconnect(VREASON_SERVER_KICK, config::messages::kick_invalid_badges, this->server ? this->server->serverAdmin : dynamic_pointer_cast<ConnectedClient>(serverInstance->getInitialServerAdmin()), true);
|
((VoiceClient *) this)->disconnect(VREASON_SERVER_KICK, config::messages::kick_invalid_badges, this->server ? this->server->serverAdmin : dynamic_pointer_cast<ConnectedClient>(serverInstance->getInitialServerAdmin()), true);
|
||||||
return command_result{error::parameter_invalid, "Invalid badges"};
|
return command_result{error::parameter_invalid, "Invalid badges"};
|
||||||
}
|
}
|
||||||
@ -4879,27 +4879,27 @@ command_result ConnectedClient::handleCommandClientEdit(Command &cmd, const std:
|
|||||||
} else if(!self && key == "client_version") {
|
} else if(!self && key == "client_version") {
|
||||||
if(client->getType() != ClientType::CLIENT_MUSIC) return command_result{error::client_invalid_type};
|
if(client->getType() != ClientType::CLIENT_MUSIC) return command_result{error::client_invalid_type};
|
||||||
if(client->properties()[property::CLIENT_OWNER] != this->getClientDatabaseId()) {
|
if(client->properties()[property::CLIENT_OWNER] != this->getClientDatabaseId()) {
|
||||||
CACHED_PERM_CHECK(permission::i_client_music_modify_power, client->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_music_needed_modify_power, client->currentChannel), true);
|
CACHED_PERM_CHECK(permission::i_client_music_modify_power, client->permissionValue(permission::i_client_music_needed_modify_power, client->currentChannel), true);
|
||||||
}
|
}
|
||||||
} else if(!self && key == "client_platform") {
|
} else if(!self && key == "client_platform") {
|
||||||
if(client->getType() != ClientType::CLIENT_MUSIC) return command_result{error::client_invalid_type};
|
if(client->getType() != ClientType::CLIENT_MUSIC) return command_result{error::client_invalid_type};
|
||||||
if(client->properties()[property::CLIENT_OWNER] != this->getClientDatabaseId()) {
|
if(client->properties()[property::CLIENT_OWNER] != this->getClientDatabaseId()) {
|
||||||
CACHED_PERM_CHECK(permission::i_client_music_modify_power, client->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_music_needed_modify_power, client->currentChannel), true);
|
CACHED_PERM_CHECK(permission::i_client_music_modify_power, client->permissionValue(permission::i_client_music_needed_modify_power, client->currentChannel), true);
|
||||||
}
|
}
|
||||||
} else if(!self && key == "client_country") {
|
} else if(!self && key == "client_country") {
|
||||||
if(client->getType() != ClientType::CLIENT_MUSIC) return command_result{error::client_invalid_type};
|
if(client->getType() != ClientType::CLIENT_MUSIC) return command_result{error::client_invalid_type};
|
||||||
if(client->properties()[property::CLIENT_OWNER] != this->getClientDatabaseId()) {
|
if(client->properties()[property::CLIENT_OWNER] != this->getClientDatabaseId()) {
|
||||||
CACHED_PERM_CHECK(permission::i_client_music_modify_power, client->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_music_needed_modify_power, client->currentChannel), true);
|
CACHED_PERM_CHECK(permission::i_client_music_modify_power, client->permissionValue(permission::i_client_music_needed_modify_power, client->currentChannel), true);
|
||||||
}
|
}
|
||||||
} else if(!self && (*info == property::CLIENT_FLAG_NOTIFY_SONG_CHANGE/* || *info == property::CLIENT_NOTIFY_SONG_MESSAGE*/)) {
|
} else if(!self && (*info == property::CLIENT_FLAG_NOTIFY_SONG_CHANGE/* || *info == property::CLIENT_NOTIFY_SONG_MESSAGE*/)) {
|
||||||
if(client->getType() != ClientType::CLIENT_MUSIC) return command_result{error::client_invalid_type};
|
if(client->getType() != ClientType::CLIENT_MUSIC) return command_result{error::client_invalid_type};
|
||||||
if(client->properties()[property::CLIENT_OWNER] != this->getClientDatabaseId()) {
|
if(client->properties()[property::CLIENT_OWNER] != this->getClientDatabaseId()) {
|
||||||
CACHED_PERM_CHECK(permission::i_client_music_modify_power, client->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_music_needed_modify_power, client->currentChannel), true);
|
CACHED_PERM_CHECK(permission::i_client_music_modify_power, client->permissionValue(permission::i_client_music_needed_modify_power, client->currentChannel), true);
|
||||||
}
|
}
|
||||||
} else if(!self && key == "client_uptime_mode") {
|
} else if(!self && key == "client_uptime_mode") {
|
||||||
if(client->getType() != ClientType::CLIENT_MUSIC) return command_result{error::client_invalid_type};
|
if(client->getType() != ClientType::CLIENT_MUSIC) return command_result{error::client_invalid_type};
|
||||||
if(client->properties()[property::CLIENT_OWNER] != this->getClientDatabaseId()) {
|
if(client->properties()[property::CLIENT_OWNER] != this->getClientDatabaseId()) {
|
||||||
CACHED_PERM_CHECK(permission::i_client_music_modify_power, client->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_music_needed_modify_power, client->currentChannel), true);
|
CACHED_PERM_CHECK(permission::i_client_music_modify_power, client->permissionValue(permission::i_client_music_needed_modify_power, client->currentChannel), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cmd[key].as<MusicClient::UptimeMode::value>() == MusicClient::UptimeMode::TIME_SINCE_SERVER_START) {
|
if(cmd[key].as<MusicClient::UptimeMode::value>() == MusicClient::UptimeMode::TIME_SINCE_SERVER_START) {
|
||||||
@ -5253,10 +5253,10 @@ command_result ConnectedClient::handleCommandClientAddPerm(Command &cmd) {
|
|||||||
return command_result{error::client_invalid_id};
|
return command_result{error::client_invalid_id};
|
||||||
auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cldbid);
|
auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cldbid);
|
||||||
|
|
||||||
PERM_CHECKR(permission::i_client_permission_modify_power, this->server->calculatePermission(permission::PERMTEST_ORDERED, cldbid, permission::i_client_needed_permission_modify_power, ClientType::CLIENT_TEAMSPEAK, nullptr), true);
|
PERM_CHECKR(permission::i_client_permission_modify_power, this->server->calculatePermission(cldbid, permission::i_client_needed_permission_modify_power, ClientType::CLIENT_TEAMSPEAK, nullptr), true);
|
||||||
|
|
||||||
auto maxValue = this->getPermissionGrantValue(permission::PERMTEST_ORDERED, permission::i_permission_modify_power, this->currentChannel);
|
auto maxValue = this->getPermissionGrantValue(permission::i_permission_modify_power, this->currentChannel);
|
||||||
bool ignoreGrant = this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_permission_modify_power_ignore, 1, this->currentChannel);
|
bool ignoreGrant = this->permissionGranted(permission::b_permission_modify_power_ignore, 1, this->currentChannel);
|
||||||
bool conOnError = cmd[0].has("continueonerror");
|
bool conOnError = cmd[0].has("continueonerror");
|
||||||
auto update_channels = false;
|
auto update_channels = false;
|
||||||
for (int index = 0; index < cmd.bulkCount(); index++) {
|
for (int index = 0; index < cmd.bulkCount(); index++) {
|
||||||
@ -5266,7 +5266,7 @@ command_result ConnectedClient::handleCommandClientAddPerm(Command &cmd) {
|
|||||||
if(permission_require_granted_value(permType) && val > maxValue)
|
if(permission_require_granted_value(permType) && val > maxValue)
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
|
|
||||||
if(!ignoreGrant && !this->permissionGrantGranted(permission::PERMTEST_ORDERED, permType, 1, this->currentChannel))
|
if(!ignoreGrant && !this->permissionGrantGranted(permType, 1, this->currentChannel))
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
|
|
||||||
if (grant) {
|
if (grant) {
|
||||||
@ -5299,16 +5299,16 @@ command_result ConnectedClient::handleCommandClientDelPerm(Command &cmd) {
|
|||||||
if(!serverInstance->databaseHelper()->validClientDatabaseId(this->server, cldbid))
|
if(!serverInstance->databaseHelper()->validClientDatabaseId(this->server, cldbid))
|
||||||
return command_result{error::client_invalid_id};
|
return command_result{error::client_invalid_id};
|
||||||
auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cldbid);
|
auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cldbid);
|
||||||
PERM_CHECKR(permission::i_client_permission_modify_power, this->server->calculatePermission(permission::PERMTEST_ORDERED, cldbid, permission::i_client_needed_permission_modify_power, ClientType::CLIENT_TEAMSPEAK, nullptr), true);
|
PERM_CHECKR(permission::i_client_permission_modify_power, this->server->calculatePermission(cldbid, permission::i_client_needed_permission_modify_power, ClientType::CLIENT_TEAMSPEAK, nullptr), true);
|
||||||
|
|
||||||
bool ignoreGrant = this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_permission_modify_power_ignore, 1, this->currentChannel);
|
bool ignoreGrant = this->permissionGranted(permission::b_permission_modify_power_ignore, 1, this->currentChannel);
|
||||||
bool conOnError = cmd[0].has("continueonerror");
|
bool conOnError = cmd[0].has("continueonerror");
|
||||||
auto onlineClients = this->server->findClientsByCldbId(cmd["cldbid"]);
|
auto onlineClients = this->server->findClientsByCldbId(cmd["cldbid"]);
|
||||||
auto update_channel = false;
|
auto update_channel = false;
|
||||||
for (int index = 0; index < cmd.bulkCount(); index++) {
|
for (int index = 0; index < cmd.bulkCount(); index++) {
|
||||||
PARSE_PERMISSION(cmd)
|
PARSE_PERMISSION(cmd)
|
||||||
|
|
||||||
if(!ignoreGrant && !this->permissionGrantGranted(permission::PERMTEST_ORDERED, permType, 1, this->currentChannel))
|
if(!ignoreGrant && !this->permissionGrantGranted(permType, 1, this->currentChannel))
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
|
|
||||||
|
|
||||||
@ -5411,19 +5411,19 @@ command_result ConnectedClient::handleCommandChannelClientDelPerm(Command &cmd)
|
|||||||
return command_result{error::parameter_invalid, "Invalid manager db id"};
|
return command_result{error::parameter_invalid, "Invalid manager db id"};
|
||||||
|
|
||||||
auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cldbid);
|
auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cldbid);
|
||||||
PERM_CHECKR(permission::i_client_permission_modify_power, this->server->calculatePermission(permission::PERMTEST_ORDERED, cmd["cldbid"], permission::i_client_needed_permission_modify_power, ClientType::CLIENT_TEAMSPEAK, nullptr), true);
|
PERM_CHECKR(permission::i_client_permission_modify_power, this->server->calculatePermission(cmd["cldbid"], permission::i_client_needed_permission_modify_power, ClientType::CLIENT_TEAMSPEAK, nullptr), true);
|
||||||
|
|
||||||
RESOLVE_CHANNEL_R(cmd["cid"], true);
|
RESOLVE_CHANNEL_R(cmd["cid"], true);
|
||||||
auto channel = dynamic_pointer_cast<ServerChannel>(l_channel->entry);
|
auto channel = dynamic_pointer_cast<ServerChannel>(l_channel->entry);
|
||||||
if(!channel) return command_result{error::vs_critical};
|
if(!channel) return command_result{error::vs_critical};
|
||||||
|
|
||||||
bool ignoreGrant = this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_permission_modify_power_ignore, 1, this->currentChannel);
|
bool ignoreGrant = this->permissionGranted(permission::b_permission_modify_power_ignore, 1, this->currentChannel);
|
||||||
bool conOnError = cmd[0].has("continueonerror"), update_view = false;
|
bool conOnError = cmd[0].has("continueonerror"), update_view = false;
|
||||||
auto cll = this->server->findClientsByCldbId(cldbid);
|
auto cll = this->server->findClientsByCldbId(cldbid);
|
||||||
for (int index = 0; index < cmd.bulkCount(); index++) {
|
for (int index = 0; index < cmd.bulkCount(); index++) {
|
||||||
PARSE_PERMISSION(cmd);
|
PARSE_PERMISSION(cmd);
|
||||||
|
|
||||||
if(!ignoreGrant && !this->permissionGrantGranted(permission::PERMTEST_ORDERED, permType, 1, this->currentChannel))
|
if(!ignoreGrant && !this->permissionGrantGranted(permType, 1, this->currentChannel))
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
|
|
||||||
if (grant) {
|
if (grant) {
|
||||||
@ -5479,11 +5479,11 @@ command_result ConnectedClient::handleCommandChannelClientAddPerm(Command &cmd)
|
|||||||
if(!channel) return command_result{error::vs_critical};
|
if(!channel) return command_result{error::vs_critical};
|
||||||
|
|
||||||
auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cldbid);
|
auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cldbid);
|
||||||
PERM_CHECK_CHANNELR(permission::i_client_permission_modify_power, this->server->calculatePermission(permission::PERMTEST_ORDERED, cmd["cldbid"], permission::i_client_needed_permission_modify_power, ClientType::CLIENT_TEAMSPEAK, channel), channel, true);
|
PERM_CHECK_CHANNELR(permission::i_client_permission_modify_power, this->server->calculatePermission(cmd["cldbid"], permission::i_client_needed_permission_modify_power, ClientType::CLIENT_TEAMSPEAK, channel), channel, true);
|
||||||
|
|
||||||
|
|
||||||
auto maxValue = this->getPermissionGrantValue(permission::PERMTEST_ORDERED, permission::i_permission_modify_power, this->currentChannel);
|
auto maxValue = this->getPermissionGrantValue(permission::i_permission_modify_power, this->currentChannel);
|
||||||
bool ignoreGrant = this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_permission_modify_power_ignore, 1, this->currentChannel);
|
bool ignoreGrant = this->permissionGranted(permission::b_permission_modify_power_ignore, 1, this->currentChannel);
|
||||||
bool conOnError = cmd[0].has("continueonerror");
|
bool conOnError = cmd[0].has("continueonerror");
|
||||||
auto onlineClientInstances = this->server->findClientsByCldbId(cldbid);
|
auto onlineClientInstances = this->server->findClientsByCldbId(cldbid);
|
||||||
bool update_view = false;
|
bool update_view = false;
|
||||||
@ -5494,7 +5494,7 @@ command_result ConnectedClient::handleCommandChannelClientAddPerm(Command &cmd)
|
|||||||
if(permission_require_granted_value(permType) && val > maxValue)
|
if(permission_require_granted_value(permType) && val > maxValue)
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
|
|
||||||
if(!ignoreGrant && !this->permissionGrantGranted(permission::PERMTEST_ORDERED, permType, 1, this->currentChannel))
|
if(!ignoreGrant && !this->permissionGrantGranted(permType, 1, this->currentChannel))
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
|
|
||||||
|
|
||||||
@ -5872,7 +5872,7 @@ command_result ConnectedClient::handleCommandPermGet(Command &cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for(const auto& entry : this->permissionValues(permission::PERMTEST_ORDERED, requrested, this->currentChannel)) {
|
for(const auto& entry : this->permissionValues(requrested, this->currentChannel)) {
|
||||||
res[index]["permsid"] = permission_mapper->permission_name(type, entry.first);;
|
res[index]["permsid"] = permission_mapper->permission_name(type, entry.first);;
|
||||||
res[index]["permid"] = entry.first;
|
res[index]["permid"] = entry.first;
|
||||||
res[index++]["permvalue"] = entry.second;
|
res[index++]["permvalue"] = entry.second;
|
||||||
@ -6374,7 +6374,7 @@ command_result ConnectedClient::handleCommandComplainAdd(Command &cmd) {
|
|||||||
|
|
||||||
auto cl = this->server->findClientsByCldbId(target);
|
auto cl = this->server->findClientsByCldbId(target);
|
||||||
if (cl.empty()) return command_result{error::client_invalid_id};
|
if (cl.empty()) return command_result{error::client_invalid_id};
|
||||||
PERM_CHECKR(permission::i_client_complain_power, cl[0]->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_needed_complain_power), true);
|
PERM_CHECKR(permission::i_client_complain_power, cl[0]->permissionValue(permission::i_client_needed_complain_power), true);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if(!serverInstance->databaseHelper()->validClientDatabaseId(target))
|
if(!serverInstance->databaseHelper()->validClientDatabaseId(target))
|
||||||
@ -6488,7 +6488,7 @@ command_result ConnectedClient::handleCommandMusicBotCreate(Command& cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
auto permissions_list = this->permissionValues(permission::PERMTEST_ORDERED, {
|
auto permissions_list = this->permissionValues({
|
||||||
permission::i_client_music_limit,
|
permission::i_client_music_limit,
|
||||||
permission::b_client_music_create_permanent,
|
permission::b_client_music_create_permanent,
|
||||||
permission::b_client_music_create_semi_permanent,
|
permission::b_client_music_create_semi_permanent,
|
||||||
@ -6543,7 +6543,7 @@ command_result ConnectedClient::handleCommandMusicBotCreate(Command& cmd) {
|
|||||||
if(cmd[0].has("cid")) return command_result{error::channel_invalid_id};
|
if(cmd[0].has("cid")) return command_result{error::channel_invalid_id};
|
||||||
} else {
|
} else {
|
||||||
CHANNEL_PERMISSION_TEST(permission::i_channel_description_view_power, permission::i_channel_needed_description_view_power, channel, false);
|
CHANNEL_PERMISSION_TEST(permission::i_channel_description_view_power, permission::i_channel_needed_description_view_power, channel, false);
|
||||||
auto permission_granted = this->calculate_permission_value(permission::i_channel_join_power, channel->channelId());
|
auto permission_granted = this->calculate_permission(permission::i_channel_join_power, channel->channelId());
|
||||||
if(!channel->permission_granted(permission::i_channel_needed_join_power, permission_granted, false))
|
if(!channel->permission_granted(permission::i_channel_needed_join_power, permission_granted, false))
|
||||||
channel = nullptr;
|
channel = nullptr;
|
||||||
}
|
}
|
||||||
@ -6600,7 +6600,7 @@ command_result ConnectedClient::handleCommandMusicBotDelete(Command& cmd) {
|
|||||||
auto bot = this->server->musicManager->findBotById(cmd["bot_id"]);
|
auto bot = this->server->musicManager->findBotById(cmd["bot_id"]);
|
||||||
if(!bot) return command_result{error::music_invalid_id};
|
if(!bot) return command_result{error::music_invalid_id};
|
||||||
|
|
||||||
bool permPower = this->permissionGranted(permission::PERMTEST_ORDERED, permission::i_client_music_delete_power, bot->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_music_needed_delete_power));
|
bool permPower = this->permissionGranted(permission::i_client_music_delete_power, bot->permissionValue(permission::i_client_music_needed_delete_power));
|
||||||
if(bot->getOwner() != this->getClientDatabaseId()) {
|
if(bot->getOwner() != this->getClientDatabaseId()) {
|
||||||
if(!permPower) return command_result{permission::i_client_music_delete_power};
|
if(!permPower) return command_result{permission::i_client_music_delete_power};
|
||||||
}
|
}
|
||||||
@ -6697,7 +6697,7 @@ command_result ConnectedClient::handleCommandMusicBotPlayerAction(Command& cmd)
|
|||||||
|
|
||||||
auto bot = this->server->musicManager->findBotById(cmd["bot_id"]);
|
auto bot = this->server->musicManager->findBotById(cmd["bot_id"]);
|
||||||
if(!bot) return command_result{error::music_invalid_id};
|
if(!bot) return command_result{error::music_invalid_id};
|
||||||
PERM_CHECK_CHANNELR(permission::i_client_music_play_power, bot->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_music_needed_play_power, bot->currentChannel), this->currentChannel, true);
|
PERM_CHECK_CHANNELR(permission::i_client_music_play_power, bot->permissionValue(permission::i_client_music_needed_play_power, bot->currentChannel), this->currentChannel, true);
|
||||||
|
|
||||||
if(cmd["action"] == 0) {
|
if(cmd["action"] == 0) {
|
||||||
bot->stopMusic();
|
bot->stopMusic();
|
||||||
@ -6963,7 +6963,7 @@ command_result ConnectedClient::handleCommandPlaylistAddPerm(ts::Command &cmd) {
|
|||||||
if(permission_require_granted_value(permType) && val > maxValue)
|
if(permission_require_granted_value(permType) && val > maxValue)
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
|
|
||||||
if(!ignoreGrant && !this->permissionGrantGranted(permission::PERMTEST_ORDERED, permType, 1, this->currentChannel))
|
if(!ignoreGrant && !this->permissionGrantGranted(permType, 1, this->currentChannel))
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
|
|
||||||
if (grant) {
|
if (grant) {
|
||||||
@ -6994,7 +6994,7 @@ command_result ConnectedClient::handleCommandPlaylistDelPerm(ts::Command &cmd) {
|
|||||||
for (int index = 0; index < cmd.bulkCount(); index++) {
|
for (int index = 0; index < cmd.bulkCount(); index++) {
|
||||||
PARSE_PERMISSION(cmd);
|
PARSE_PERMISSION(cmd);
|
||||||
|
|
||||||
if(!ignoreGrant && !this->permissionGrantGranted(permission::PERMTEST_ORDERED, permType, 1, this->currentChannel))
|
if(!ignoreGrant && !this->permissionGrantGranted(permType, 1, this->currentChannel))
|
||||||
return command_result{permission::i_permission_modify_power};
|
return command_result{permission::i_permission_modify_power};
|
||||||
|
|
||||||
if (grant) {
|
if (grant) {
|
||||||
@ -7128,7 +7128,7 @@ command_result ConnectedClient::handleCommandMusicBotQueueList(Command& cmd) {
|
|||||||
|
|
||||||
auto bot = this->server->musicManager->findBotById(cmd["bot_id"]);
|
auto bot = this->server->musicManager->findBotById(cmd["bot_id"]);
|
||||||
if(!bot) return command_result{error::music_invalid_id};
|
if(!bot) return command_result{error::music_invalid_id};
|
||||||
PERM_CHECK_CHANNELR(permission::i_client_music_info, bot->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_music_needed_info, bot->currentChannel), this->currentChannel, true);
|
PERM_CHECK_CHANNELR(permission::i_client_music_info, bot->permissionValue(permission::i_client_music_needed_info, bot->currentChannel), this->currentChannel, true);
|
||||||
|
|
||||||
|
|
||||||
bool bulked = cmd.hasParm("bulk") || cmd.hasParm("balk") || cmd.hasParm("pipe") || cmd.hasParm("bar") || cmd.hasParm("paypal");
|
bool bulked = cmd.hasParm("bulk") || cmd.hasParm("balk") || cmd.hasParm("pipe") || cmd.hasParm("bar") || cmd.hasParm("paypal");
|
||||||
@ -7209,7 +7209,7 @@ command_result ConnectedClient::handleCommandMusicBotQueueAdd(Command& cmd) {
|
|||||||
|
|
||||||
auto bot = this->server->musicManager->findBotById(cmd["bot_id"]);
|
auto bot = this->server->musicManager->findBotById(cmd["bot_id"]);
|
||||||
if(!bot) return command_result{error::music_invalid_id};
|
if(!bot) return command_result{error::music_invalid_id};
|
||||||
PERM_CHECK_CHANNELR(permission::i_client_music_play_power, bot->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_music_needed_play_power, bot->currentChannel), this->currentChannel, true);
|
PERM_CHECK_CHANNELR(permission::i_client_music_play_power, bot->permissionValue(permission::i_client_music_needed_play_power, bot->currentChannel), this->currentChannel, true);
|
||||||
|
|
||||||
MusicClient::loader_t loader;
|
MusicClient::loader_t loader;
|
||||||
auto& type = cmd[0]["type"];
|
auto& type = cmd[0]["type"];
|
||||||
@ -7245,7 +7245,7 @@ command_result ConnectedClient::handleCommandMusicBotQueueRemove(Command& cmd) {
|
|||||||
|
|
||||||
auto bot = this->server->musicManager->findBotById(cmd["bot_id"]);
|
auto bot = this->server->musicManager->findBotById(cmd["bot_id"]);
|
||||||
if(!bot) return command_result{error::music_invalid_id};
|
if(!bot) return command_result{error::music_invalid_id};
|
||||||
PERM_CHECK_CHANNELR(permission::i_client_music_play_power, bot->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_music_needed_play_power, bot->currentChannel), this->currentChannel, true);
|
PERM_CHECK_CHANNELR(permission::i_client_music_play_power, bot->permissionValue(permission::i_client_music_needed_play_power, bot->currentChannel), this->currentChannel, true);
|
||||||
|
|
||||||
std::deque<std::shared_ptr<music::SongInfo>> songs;
|
std::deque<std::shared_ptr<music::SongInfo>> songs;
|
||||||
for(int index = 0; index < cmd.bulkCount(); index++) {
|
for(int index = 0; index < cmd.bulkCount(); index++) {
|
||||||
@ -7277,7 +7277,7 @@ command_result ConnectedClient::handleCommandMusicBotQueueReorder(Command& cmd)
|
|||||||
|
|
||||||
auto bot = this->server->musicManager->findBotById(cmd["bot_id"]);
|
auto bot = this->server->musicManager->findBotById(cmd["bot_id"]);
|
||||||
if(!bot) return command_result{error::music_invalid_id};
|
if(!bot) return command_result{error::music_invalid_id};
|
||||||
PERM_CHECK_CHANNELR(permission::i_client_music_play_power, bot->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_music_needed_play_power, bot->currentChannel), this->currentChannel, true);
|
PERM_CHECK_CHANNELR(permission::i_client_music_play_power, bot->permissionValue(permission::i_client_music_needed_play_power, bot->currentChannel), this->currentChannel, true);
|
||||||
|
|
||||||
auto entry = bot->queue()->find_queue(cmd["song_id"]);
|
auto entry = bot->queue()->find_queue(cmd["song_id"]);
|
||||||
if(!entry) return command_result{error::database_empty_result};
|
if(!entry) return command_result{error::database_empty_result};
|
||||||
@ -7299,7 +7299,7 @@ command_result ConnectedClient::handleCommandMusicBotPlaylistAssign(ts::Command
|
|||||||
auto bot = ref_server->musicManager->findBotById(cmd["bot_id"]);
|
auto bot = ref_server->musicManager->findBotById(cmd["bot_id"]);
|
||||||
if(!bot) return command_result{error::music_invalid_id};
|
if(!bot) return command_result{error::music_invalid_id};
|
||||||
if(bot->getOwner() != this->getClientDatabaseId())
|
if(bot->getOwner() != this->getClientDatabaseId())
|
||||||
PERM_CHECK_CHANNELR(permission::i_client_music_play_power, bot->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_music_needed_play_power, bot->currentChannel), this->currentChannel, true);
|
PERM_CHECK_CHANNELR(permission::i_client_music_play_power, bot->permissionValue(permission::i_client_music_needed_play_power, bot->currentChannel), this->currentChannel, true);
|
||||||
|
|
||||||
auto playlist = ref_server->musicManager->find_playlist(cmd["playlist_id"]);
|
auto playlist = ref_server->musicManager->find_playlist(cmd["playlist_id"]);
|
||||||
if(!playlist && cmd["playlist_id"] != 0) return command_result{error::playlist_invalid_id};
|
if(!playlist && cmd["playlist_id"] != 0) return command_result{error::playlist_invalid_id};
|
||||||
@ -7530,8 +7530,8 @@ command_result ConnectedClient::handleCommandQueryList(ts::Command &cmd) {
|
|||||||
if(!server && server_id != EmptyServerId && server_id != 0)
|
if(!server && server_id != EmptyServerId && server_id != 0)
|
||||||
return command_result{error::server_invalid_id};
|
return command_result{error::server_invalid_id};
|
||||||
|
|
||||||
auto global_list = this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_client_query_list, 1, nullptr, true, nullptr, server, true);
|
auto global_list = this->permissionGranted(permission::b_client_query_list, 1, nullptr, true, nullptr, server, true);
|
||||||
auto own_list = global_list || this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_client_query_list_own, 1, nullptr, true, nullptr, server, true);
|
auto own_list = global_list || this->permissionGranted(permission::b_client_query_list_own, 1, nullptr, true, nullptr, server, true);
|
||||||
|
|
||||||
if(!own_list && !global_list)
|
if(!own_list && !global_list)
|
||||||
return command_result{permission::b_client_query_list};
|
return command_result{permission::b_client_query_list};
|
||||||
@ -7575,7 +7575,7 @@ command_result ConnectedClient::handleCommandQueryCreate(ts::Command &cmd) {
|
|||||||
if(!server && server_id != EmptyServerId && server_id != 0)
|
if(!server && server_id != EmptyServerId && server_id != 0)
|
||||||
return command_result{error::server_invalid_id};
|
return command_result{error::server_invalid_id};
|
||||||
|
|
||||||
if(!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_client_query_create, 1, nullptr, true, nullptr, server, true))
|
if(!this->permissionGranted(permission::b_client_query_create, 1, nullptr, true, nullptr, server, true))
|
||||||
return command_result{permission::b_client_query_create};
|
return command_result{permission::b_client_query_create};
|
||||||
|
|
||||||
auto username = cmd["client_login_name"].as<string>();
|
auto username = cmd["client_login_name"].as<string>();
|
||||||
@ -7613,8 +7613,8 @@ command_result ConnectedClient::handleCommandQueryDelete(ts::Command &cmd) {
|
|||||||
return command_result{error::server_invalid_id};
|
return command_result{error::server_invalid_id};
|
||||||
*/
|
*/
|
||||||
|
|
||||||
auto delete_all = this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_client_query_delete, 1, nullptr, true, nullptr, server, true);
|
auto delete_all = this->permissionGranted(permission::b_client_query_delete, 1, nullptr, true, nullptr, server, true);
|
||||||
auto delete_own = delete_all || this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_client_query_delete_own, 1, nullptr, true, nullptr, server, true);
|
auto delete_own = delete_all || this->permissionGranted(permission::b_client_query_delete_own, 1, nullptr, true, nullptr, server, true);
|
||||||
|
|
||||||
if(account->unique_id == this->getUid()) {
|
if(account->unique_id == this->getUid()) {
|
||||||
if(!delete_own)
|
if(!delete_own)
|
||||||
@ -7643,8 +7643,8 @@ command_result ConnectedClient::handleCommandQueryRename(ts::Command &cmd) {
|
|||||||
if(!server && account->bound_server != 0)
|
if(!server && account->bound_server != 0)
|
||||||
return command_result{error::server_invalid_id};
|
return command_result{error::server_invalid_id};
|
||||||
|
|
||||||
auto rename_all = this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_client_query_rename, 1, nullptr, true, nullptr, server, true);
|
auto rename_all = this->permissionGranted(permission::b_client_query_rename, 1, nullptr, true, nullptr, server, true);
|
||||||
auto rename_own = rename_all || this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_client_query_rename_own, 1, nullptr, true, nullptr, server, true);
|
auto rename_own = rename_all || this->permissionGranted(permission::b_client_query_rename_own, 1, nullptr, true, nullptr, server, true);
|
||||||
|
|
||||||
if(account->unique_id == this->getUid()) {
|
if(account->unique_id == this->getUid()) {
|
||||||
if(!rename_own)
|
if(!rename_own)
|
||||||
@ -7676,8 +7676,8 @@ command_result ConnectedClient::handleCommandQueryChangePassword(ts::Command &cm
|
|||||||
if(!server && account->bound_server != 0)
|
if(!server && account->bound_server != 0)
|
||||||
return command_result{error::server_invalid_id};
|
return command_result{error::server_invalid_id};
|
||||||
|
|
||||||
auto change_all = this->permissionGranted(permission::PERMTEST_ORDERED, server ? permission::b_client_query_change_password : permission::b_client_query_change_password_global, 1, nullptr, true, nullptr, server, true);
|
auto change_all = this->permissionGranted(server ? permission::b_client_query_change_password : permission::b_client_query_change_password_global, 1, nullptr, true, nullptr, server, true);
|
||||||
auto change_own = change_all || this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_client_query_change_own_password, 1, nullptr, true, nullptr, server, true);
|
auto change_own = change_all || this->permissionGranted(permission::b_client_query_change_own_password, 1, nullptr, true, nullptr, server, true);
|
||||||
|
|
||||||
auto password = cmd[0].has("client_login_password") ? cmd["client_login_password"].as<string>() : "";
|
auto password = cmd[0].has("client_login_password") ? cmd["client_login_password"].as<string>() : "";
|
||||||
|
|
||||||
@ -7707,7 +7707,7 @@ command_result ConnectedClient::handleCommandDummy_IpChange(ts::Command &cmd) {
|
|||||||
CMD_REF_SERVER(server);
|
CMD_REF_SERVER(server);
|
||||||
logMessage(this->getServerId(), "[{}] Address changed from {} to {}", CLIENT_STR_LOG_PREFIX, cmd["old_ip"].string(), cmd["new_ip"].string());
|
logMessage(this->getServerId(), "[{}] Address changed from {} to {}", CLIENT_STR_LOG_PREFIX, cmd["old_ip"].string(), cmd["new_ip"].string());
|
||||||
|
|
||||||
if(geoloc::provider_vpn && !this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_client_ignore_vpn, 1)) {
|
if(geoloc::provider_vpn && !this->permissionGranted(permission::b_client_ignore_vpn, 1)) {
|
||||||
auto provider = this->isAddressV4() ? geoloc::provider_vpn->resolveInfoV4(this->getPeerIp(), true) : geoloc::provider_vpn->resolveInfoV6(this->getPeerIp(), true);
|
auto provider = this->isAddressV4() ? geoloc::provider_vpn->resolveInfoV4(this->getPeerIp(), true) : geoloc::provider_vpn->resolveInfoV6(this->getPeerIp(), true);
|
||||||
if(provider) {
|
if(provider) {
|
||||||
this->disconnect(strvar::transform(ts::config::messages::kick_vpn, strvar::StringValue{"provider.name", provider->name}, strvar::StringValue{"provider.website", provider->side}));
|
this->disconnect(strvar::transform(ts::config::messages::kick_vpn, strvar::StringValue{"provider.name", provider->name}, strvar::StringValue{"provider.website", provider->side}));
|
||||||
@ -7764,10 +7764,10 @@ command_result ConnectedClient::handleCommandConversationHistory(ts::Command &co
|
|||||||
command[0]["cpw"] = "";
|
command[0]["cpw"] = "";
|
||||||
|
|
||||||
if (!channel->passwordMatch(command["cpw"], true))
|
if (!channel->passwordMatch(command["cpw"], true))
|
||||||
if (!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_channel_join_ignore_password, 1, channel, true))
|
if (!this->permissionGranted(permission::b_channel_join_ignore_password, 1, channel, true))
|
||||||
return command_result{error::channel_invalid_password, "invalid password"};
|
return command_result{error::channel_invalid_password, "invalid password"};
|
||||||
|
|
||||||
if(!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_channel_ignore_join_power, 1, channel, true)) {
|
if(!this->permissionGranted(permission::b_channel_ignore_join_power, 1, channel, true)) {
|
||||||
CHANNEL_PERMISSION_TEST(permission::i_channel_join_power, permission::i_channel_needed_join_power, channel, false);
|
CHANNEL_PERMISSION_TEST(permission::i_channel_join_power, permission::i_channel_needed_join_power, channel, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7894,15 +7894,15 @@ command_result ConnectedClient::handleCommandConversationFetch(ts::Command &cmd)
|
|||||||
bulk["cpw"] = "";
|
bulk["cpw"] = "";
|
||||||
|
|
||||||
if (!channel->passwordMatch(bulk["cpw"], true))
|
if (!channel->passwordMatch(bulk["cpw"], true))
|
||||||
if (!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_channel_join_ignore_password, 1, channel, true)) {
|
if (!this->permissionGranted(permission::b_channel_join_ignore_password, 1, channel, true)) {
|
||||||
auto error = findError("channel_invalid_password");
|
auto error = findError("channel_invalid_password");
|
||||||
result_bulk["error_id"] = error.errorId;
|
result_bulk["error_id"] = error.errorId;
|
||||||
result_bulk["error_msg"] = error.message;
|
result_bulk["error_msg"] = error.message;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_channel_ignore_join_power, 1, channel, true)) {
|
if(!this->permissionGranted(permission::b_channel_ignore_join_power, 1, channel, true)) {
|
||||||
auto permission_granted = this->calculate_permission_value(permission::i_channel_join_power, channel->channelId());
|
auto permission_granted = this->calculate_permission(permission::i_channel_join_power, channel->channelId());
|
||||||
if(!channel->permission_granted(permission::i_channel_needed_join_power, permission_granted, false)) {
|
if(!channel->permission_granted(permission::i_channel_needed_join_power, permission_granted, false)) {
|
||||||
auto error = findError("server_insufficeient_permissions");
|
auto error = findError("server_insufficeient_permissions");
|
||||||
result_bulk["error_id"] = error.errorId;
|
result_bulk["error_id"] = error.errorId;
|
||||||
@ -7966,14 +7966,14 @@ command_result ConnectedClient::handleCommandConversationMessageDelete(ts::Comma
|
|||||||
bulk["cpw"] = "";
|
bulk["cpw"] = "";
|
||||||
|
|
||||||
if (!channel->passwordMatch(bulk["cpw"], true))
|
if (!channel->passwordMatch(bulk["cpw"], true))
|
||||||
if (!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_channel_join_ignore_password, 1, channel, true))
|
if (!this->permissionGranted(permission::b_channel_join_ignore_password, 1, channel, true))
|
||||||
return command_result{error::channel_invalid_password};
|
return command_result{error::channel_invalid_password};
|
||||||
|
|
||||||
if (!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_channel_conversation_message_delete, 1, channel))
|
if (!this->permissionGranted(permission::b_channel_conversation_message_delete, 1, channel))
|
||||||
return command_result{permission::b_channel_conversation_message_delete};
|
return command_result{permission::b_channel_conversation_message_delete};
|
||||||
|
|
||||||
if(!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_channel_ignore_join_power, 1, channel, true)) {
|
if(!this->permissionGranted(permission::b_channel_ignore_join_power, 1, channel, true)) {
|
||||||
auto permission_granted = this->calculate_permission_value(permission::i_channel_join_power, channel->channelId());
|
auto permission_granted = this->calculate_permission(permission::i_channel_join_power, channel->channelId());
|
||||||
if(!channel->permission_granted(permission::i_channel_needed_join_power, permission_granted, false))
|
if(!channel->permission_granted(permission::i_channel_needed_join_power, permission_granted, false))
|
||||||
return command_result{permission::i_channel_needed_join_power};
|
return command_result{permission::i_channel_needed_join_power};
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <misc/sassert.h>
|
#include <misc/sassert.h>
|
||||||
#include <misc/timer.h>
|
#include <misc/timer.h>
|
||||||
#include "./web/WebClient.h"
|
#include "./web/WebClient.h"
|
||||||
|
#include "query/command3.h"
|
||||||
|
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@ -35,6 +36,18 @@ do { \
|
|||||||
} \
|
} \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
#define INVOKER_NEW(command, invoker) \
|
||||||
|
do { \
|
||||||
|
if(invoker) { \
|
||||||
|
command.put_unchecked(0, "invokerid", invoker->getClientId()); \
|
||||||
|
command.put_unchecked(0, "invokername", invoker->getDisplayName()); \
|
||||||
|
command.put_unchecked(0, "invokeruid", invoker->getUid()); \
|
||||||
|
} else { \
|
||||||
|
command.put_unchecked(0, "invokerid", "0"); \
|
||||||
|
command.put_unchecked(0, "invokername", "undefined"); \
|
||||||
|
command.put_unchecked(0, "invokeruid", "undefined"); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
bool ConnectedClient::notifyServerGroupList() {
|
bool ConnectedClient::notifyServerGroupList() {
|
||||||
Command cmd(this->getExternalType() == CLIENT_TEAMSPEAK ? "notifyservergrouplist" : "");
|
Command cmd(this->getExternalType() == CLIENT_TEAMSPEAK ? "notifyservergrouplist" : "");
|
||||||
@ -65,30 +78,34 @@ bool ConnectedClient::notifyServerGroupList() {
|
|||||||
|
|
||||||
|
|
||||||
bool ConnectedClient::notifyGroupPermList(const std::shared_ptr<Group>& group, bool as_sid) {
|
bool ConnectedClient::notifyGroupPermList(const std::shared_ptr<Group>& group, bool as_sid) {
|
||||||
Command cmd(this->getExternalType() == CLIENT_TEAMSPEAK ? group->target() == GROUPTARGET_SERVER ? "notifyservergrouppermlist" : "notifychannelgrouppermlist" : "");
|
ts::command_builder result{this->getExternalType() == CLIENT_TEAMSPEAK ? group->target() == GROUPTARGET_SERVER ? "notifyservergrouppermlist" : "notifychannelgrouppermlist" : ""};
|
||||||
|
|
||||||
if (group->target() == GROUPTARGET_SERVER)
|
if (group->target() == GROUPTARGET_SERVER)
|
||||||
cmd["sgid"] = group->groupId();
|
result.put_unchecked(0, "sgid", group->groupId());
|
||||||
else
|
else
|
||||||
cmd["cgid"] = group->groupId();
|
result.put_unchecked(0, "cgid", group->groupId());
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
|
||||||
auto permissions = group->permissions()->permissions();
|
auto permissions = group->permissions()->permissions();
|
||||||
auto permission_mapper = serverInstance->getPermissionMapper();
|
auto permission_mapper = serverInstance->getPermissionMapper();
|
||||||
auto client_type = this->getType();
|
auto client_type = this->getType();
|
||||||
|
|
||||||
|
result.reserve_bulks(permissions.size() * 2);
|
||||||
for (const auto &permission_data : permissions) {
|
for (const auto &permission_data : permissions) {
|
||||||
auto& permission = get<1>(permission_data);
|
auto& permission = get<1>(permission_data);
|
||||||
if(!permission.flags.value_set)
|
if(!permission.flags.value_set)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if(as_sid) {
|
if(as_sid) {
|
||||||
cmd[index]["permsid"] = permission_mapper->permission_name(client_type, get<0>(permission_data));
|
result.put_unchecked(index, "permsid", permission_mapper->permission_name(client_type, get<0>(permission_data)));
|
||||||
} else {
|
} else {
|
||||||
cmd[index]["permid"] = (uint16_t) get<0>(permission_data);
|
result.put_unchecked(index, "permid", (uint16_t) get<0>(permission_data));
|
||||||
}
|
}
|
||||||
cmd[index]["permvalue"] = permission.values.value;
|
|
||||||
cmd[index]["permnegated"] = permission.flags.negate;
|
result.put_unchecked(index, "permvalue", permission.values.value);
|
||||||
cmd[index]["permskip"] = permission.flags.skip;
|
result.put_unchecked(index, "permnegated", permission.flags.negate);
|
||||||
|
result.put_unchecked(index, "permskip", permission.flags.skip);
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
for (const auto &permission_data : permissions) {
|
for (const auto &permission_data : permissions) {
|
||||||
@ -96,21 +113,23 @@ bool ConnectedClient::notifyGroupPermList(const std::shared_ptr<Group>& group, b
|
|||||||
if(!permission.flags.grant_set)
|
if(!permission.flags.grant_set)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
||||||
if(as_sid) {
|
if(as_sid) {
|
||||||
cmd[index]["permsid"] = permission_mapper->permission_name_grant(client_type, get<0>(permission_data));
|
result.put_unchecked(index, "permsid", permission_mapper->permission_name_grant(client_type, get<0>(permission_data)));
|
||||||
} else {
|
} else {
|
||||||
cmd[index]["permid"] = (uint16_t) (get<0>(permission_data) | PERM_ID_GRANT);
|
result.put_unchecked(index, "permid", (uint16_t) (get<0>(permission_data) | PERM_ID_GRANT));
|
||||||
}
|
}
|
||||||
cmd[index]["permvalue"] = permission.values.grant;
|
|
||||||
cmd[index]["permnegated"] = permission.flags.negate;
|
result.put_unchecked(index, "permvalue", permission.values.value);
|
||||||
cmd[index]["permskip"] = permission.flags.skip;
|
result.put_unchecked(index, "permnegated", permission.flags.negate);
|
||||||
|
result.put_unchecked(index, "permskip", permission.flags.skip);
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index == 0)
|
if (index == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
this->sendCommand(cmd);
|
this->sendCommand(result); //Need hack
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -341,7 +360,7 @@ bool ConnectedClient::notifyConnectionInfo(const shared_ptr<ConnectedClient> &ta
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(target->getClientId() == this->getClientId() || this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_client_remoteaddress_view, 1, target->currentChannel, true)) {
|
if(target->getClientId() == this->getClientId() || permission::v2::permission_granted(1, this->calculate_permission(permission::b_client_remoteaddress_view, this->getChannelId()))) {
|
||||||
notify["connection_client_ip"] = target->getLoggingPeerIp();
|
notify["connection_client_ip"] = target->getLoggingPeerIp();
|
||||||
notify["connection_client_port"] = target->getPeerPort();
|
notify["connection_client_port"] = target->getPeerPort();
|
||||||
}
|
}
|
||||||
@ -569,29 +588,29 @@ bool ConnectedClient::notifyClientEnterView(const std::shared_ptr<ConnectedClien
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Command cmd("notifycliententerview");
|
ts::command_builder builder{"notifycliententerview", 1024, 1};
|
||||||
|
|
||||||
cmd["cfid"] = from ? from->channelId() : 0;
|
builder.put_unchecked(0, "cfid", from ? from->channelId() : 0);
|
||||||
cmd["ctid"] = to ? to->channelId() : 0;
|
builder.put_unchecked(0, "ctid", to ? to->channelId() : 0);
|
||||||
cmd["reasonid"] = reasonId;
|
builder.put_unchecked(0, "reasonid", reasonId);
|
||||||
INVOKER(cmd, invoker);
|
INVOKER_NEW(builder, invoker);
|
||||||
switch (reasonId) {
|
switch (reasonId) {
|
||||||
case ViewReasonId::VREASON_MOVED:
|
case ViewReasonId::VREASON_MOVED:
|
||||||
case ViewReasonId::VREASON_BAN:
|
case ViewReasonId::VREASON_BAN:
|
||||||
case ViewReasonId::VREASON_CHANNEL_KICK:
|
case ViewReasonId::VREASON_CHANNEL_KICK:
|
||||||
case ViewReasonId::VREASON_SERVER_KICK:
|
case ViewReasonId::VREASON_SERVER_KICK:
|
||||||
cmd["reasonmsg"] = reason;
|
builder.put_unchecked(0, "reasonmsg", reason);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &elm : client->properties()->list_properties(property::FLAG_CLIENT_VIEW, this->getType() == CLIENT_TEAMSPEAK ? property::FLAG_NEW : (uint16_t) 0)) {
|
for (const auto &elm : client->properties()->list_properties(property::FLAG_CLIENT_VIEW, this->getType() == CLIENT_TEAMSPEAK ? property::FLAG_NEW : (uint16_t) 0)) {
|
||||||
cmd[elm.type().name] = elm.value();
|
builder.put_unchecked(0, elm.type().name, elm.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
visibleClients.emplace_back(client);
|
visibleClients.emplace_back(client);
|
||||||
this->sendCommand(cmd);
|
this->sendCommand(builder);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -66,8 +66,8 @@ inline string filterUrl(string in){
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline void permissionableCommand(ConnectedClient* client, stringstream& ss, const std::string& cmd, permission::PermissionType perm, permission::PermissionType sec = permission::unknown) {
|
inline void permissionableCommand(ConnectedClient* client, stringstream& ss, const std::string& cmd, permission::PermissionType perm, permission::PermissionType sec = permission::unknown) {
|
||||||
auto permA = perm == permission::unknown || client->permissionGranted(permission::PERMTEST_ORDERED, perm, 1, client->getChannel(), true);
|
auto permA = perm == permission::unknown || permission::v2::permission_granted(1, client->calculate_permission(perm, client->getChannelId()));
|
||||||
auto permB = permA || (sec != permission::unknown && client->permissionGranted(permission::PERMTEST_ORDERED, sec, 1, client->getChannel(), true));
|
auto permB = permA || (sec != permission::unknown && permission::v2::permission_granted(1, client->calculate_permission(sec, client->getChannelId())));
|
||||||
if(!(permA || permB)) {
|
if(!(permA || permB)) {
|
||||||
ss << "[color=red]" << cmd << "[/color]" << endl;
|
ss << "[color=red]" << cmd << "[/color]" << endl;
|
||||||
} else {
|
} else {
|
||||||
@ -98,7 +98,8 @@ bool ConnectedClient::handleTextMessage(ChatMessageMode mode, std::string text,
|
|||||||
|
|
||||||
|
|
||||||
#define PERM_CHECK_BOT(perm, reqperm, err) \
|
#define PERM_CHECK_BOT(perm, reqperm, err) \
|
||||||
if(bot->properties()[property::CLIENT_OWNER] != this->getClientDatabaseId() && !this->permissionGranted(permission::PERMTEST_ORDERED, permission::perm, this->permissionValue(permission::PERMTEST_ORDERED, permission::reqperm, this->currentChannel), this->currentChannel, true)) { \
|
if(bot->properties()[property::CLIENT_OWNER] != this->getClientDatabaseId() && \
|
||||||
|
!permission::v2::permission_granted(bot->calculate_permission(permission::reqperm, bot->getChannelId()), this->calculate_permission(permission::perm, bot->getChannelId()))) { \
|
||||||
send_message(serverInstance->musicRoot(), err); \
|
send_message(serverInstance->musicRoot(), err); \
|
||||||
return true; \
|
return true; \
|
||||||
}
|
}
|
||||||
@ -170,7 +171,7 @@ bool ConnectedClient::handle_text_command(
|
|||||||
server = true;
|
server = true;
|
||||||
|
|
||||||
string locationStr = server ? "on this server" : "in this channel";
|
string locationStr = server ? "on this server" : "in this channel";
|
||||||
if(!this->permissionGranted(permission::PERMTEST_ORDERED, server ? permission::b_client_music_server_list : permission::b_client_music_channel_list, 1, this->currentChannel, true)) {
|
if(!permission::v2::permission_granted(1, this->calculate_permission(server ? permission::b_client_music_server_list : permission::b_client_music_channel_list, this->getChannelId()))) {
|
||||||
send_message(serverInstance->musicRoot(), "You don't have the permission to list all music bots " + locationStr);
|
send_message(serverInstance->musicRoot(), "You don't have the permission to list all music bots " + locationStr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -197,7 +198,9 @@ bool ConnectedClient::handle_text_command(
|
|||||||
auto botId = static_cast<ClientDbId>(stoll(arguments[1]));
|
auto botId = static_cast<ClientDbId>(stoll(arguments[1]));
|
||||||
auto bot = this->server->musicManager->findBotById(botId);
|
auto bot = this->server->musicManager->findBotById(botId);
|
||||||
if (!bot) ERR(serverInstance->musicRoot(), "Could not find target bot");
|
if (!bot) ERR(serverInstance->musicRoot(), "Could not find target bot");
|
||||||
if(bot->properties()[property::CLIENT_OWNER] != this->getClientDatabaseId() && !this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_client_music_channel_list, 1, this->currentChannel, true) && !this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_client_music_server_list, 1, this->currentChannel, true)) { //No perms for listing
|
if(bot->properties()[property::CLIENT_OWNER] != this->getClientDatabaseId() &&
|
||||||
|
!permission::v2::permission_granted(1, this->calculate_permission(permission::b_client_music_channel_list, this->getChannelId())) &&
|
||||||
|
!permission::v2::permission_granted(1, this->calculate_permission(permission::b_client_music_server_list, this->getChannelId()))) { //No perms for listing
|
||||||
send_message(serverInstance->musicRoot(), "You don't have the permission to select a music bot");
|
send_message(serverInstance->musicRoot(), "You don't have the permission to select a music bot");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -430,9 +433,9 @@ bool ConnectedClient::handle_text_command(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto max_volume = this->cached_permission_value(permission::i_client_music_create_modify_max_volume);
|
auto max_volume = this->calculate_permission(permission::i_client_music_create_modify_max_volume, 0);
|
||||||
if(max_volume != permNotGranted && !this->permission_granted(max_volume, volume, true)) {
|
if(max_volume.has_value && !permission::v2::permission_granted(volume, max_volume)) {
|
||||||
send_message(bot, "You don't have the permission to use higher volumes that " + to_string(max_volume) + "%");
|
send_message(bot, "You don't have the permission to use higher volumes that " + to_string(max_volume.value) + "%");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -567,8 +570,8 @@ bool ConnectedClient::handle_text_command(
|
|||||||
stringstream ss;
|
stringstream ss;
|
||||||
ss << "Available music bot commands: ([color=green]green[/color] = permission granted | [color=red]red[/color] = insufficient permissions)" << endl;
|
ss << "Available music bot commands: ([color=green]green[/color] = permission granted | [color=red]red[/color] = insufficient permissions)" << endl;
|
||||||
|
|
||||||
bool has_list_server = this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_client_music_server_list, 1, this->currentChannel);
|
bool has_list_server = permission::v2::permission_granted(1, this->calculate_permission(permission::b_client_music_server_list, this->getChannelId()));
|
||||||
bool has_list_channel = this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_client_music_channel_list, 1, this->currentChannel);
|
bool has_list_channel = permission::v2::permission_granted(1, this->calculate_permission(permission::b_client_music_channel_list, this->getChannelId()));
|
||||||
permissionableCommand(this, ss, string() + " .mbot list [<[color=" + (has_list_server ? "green" : "red") + "]server[/color]|[color=" + (has_list_channel ? "green" : "red") + "]channel[/color]>]", permission::b_client_music_channel_list, permission::b_client_music_server_list);
|
permissionableCommand(this, ss, string() + " .mbot list [<[color=" + (has_list_server ? "green" : "red") + "]server[/color]|[color=" + (has_list_channel ? "green" : "red") + "]channel[/color]>]", permission::b_client_music_channel_list, permission::b_client_music_server_list);
|
||||||
permissionableCommand(this, ss, " " + ts::config::music::command_prefix + "mbot select <id>", permission::b_client_music_channel_list, permission::b_client_music_server_list);
|
permissionableCommand(this, ss, " " + ts::config::music::command_prefix + "mbot select <id>", permission::b_client_music_channel_list, permission::b_client_music_server_list);
|
||||||
permissionableCommand(this, ss, " " + ts::config::music::command_prefix + "mbot formats", permission::unknown);
|
permissionableCommand(this, ss, " " + ts::config::music::command_prefix + "mbot formats", permission::unknown);
|
||||||
|
@ -130,126 +130,32 @@ bool DataClient::loadDataForCurrentServer() { //TODO for query
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
permission::v2::PermissionFlaggedValue DataClient::permissionValueFlagged(permission::PermissionType type, const std::shared_ptr<BasicChannel>& target, std::shared_ptr<CalculateCache> cache, std::shared_ptr<TSServer> server, bool server_defined) {
|
std::vector<std::pair<permission::PermissionType, permission::v2::PermissionFlaggedValue>> DataClient::calculate_permissions(
|
||||||
if(!server_defined && !server)
|
const std::deque<permission::PermissionType> &permissions,
|
||||||
server = this->server;
|
ChannelId channel,
|
||||||
|
bool granted,
|
||||||
|
std::shared_ptr<CalculateCache> cache) {
|
||||||
|
if(permissions.empty()) return {};
|
||||||
|
|
||||||
if(server) {
|
if(!cache)
|
||||||
auto result = server->calculatePermissions2(this->getClientDatabaseId(), {type}, this->getType(), target ? target->channelId() : 0, false, cache);
|
cache = std::make_shared<CalculateCache>();
|
||||||
if(result.empty() || result[0].first != type)
|
if(!cache->client_permissions) /* so we don't have to load that shit later */
|
||||||
return permission::v2::empty_permission_flagged_value;
|
cache->client_permissions = this->clientPermissions;
|
||||||
return result[0].second;
|
if(channel == -1)
|
||||||
} else {
|
channel = this->currentChannel ? this->currentChannel->channelId() : 0;
|
||||||
/* if you're not bound to a channel then you cant be bound to a server as well. */
|
|
||||||
bool permission_set = false;
|
auto ref_server = this->server;
|
||||||
permission::PermissionValue result = permNotGranted;
|
if(ref_server)
|
||||||
for(const auto &gr : serverInstance->getGroupManager()->getServerGroups(this->getClientDatabaseId(), this->getType())){
|
return ref_server->calculate_permissions(permissions, this->getClientDatabaseId(), this->getType(), channel, granted, cache);
|
||||||
auto group_permissions = gr->group->permissions();
|
else
|
||||||
auto flagged_permissions = group_permissions->permission_value_flagged(type);
|
return serverInstance->calculate_permissions(permissions, this->getClientDatabaseId(), this->getType(), channel, granted, cache);
|
||||||
if(flagged_permissions.has_value) {
|
|
||||||
if(flagged_permissions.value > result || flagged_permissions.value == -1) {
|
|
||||||
result = flagged_permissions.value;
|
|
||||||
permission_set = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {result, permission_set};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
permission::PermissionValue DataClient::permissionValue(permission::PermissionTestType test, permission::PermissionType type, const std::shared_ptr<BasicChannel>& target, std::shared_ptr<CalculateCache> cache, std::shared_ptr<TSServer> server, bool server_defined) {
|
permission::v2::PermissionFlaggedValue DataClient::calculate_permission(
|
||||||
auto result = this->permissionValueFlagged(type, target, cache, server, server_defined);
|
permission::PermissionType permission, ChannelId channel, bool granted, std::shared_ptr<CalculateCache> cache) {
|
||||||
if(result.has_value)
|
auto result = this->calculate_permissions({permission}, channel, granted, cache);
|
||||||
return result.value;
|
if(result.empty()) return {0, false};
|
||||||
return permNotGranted;
|
return result.back().second;
|
||||||
}
|
|
||||||
|
|
||||||
std::deque<std::pair<permission::PermissionType, permission::PermissionValue>> DataClient::permissionValues(permission::PermissionTestType test, const std::deque<permission::PermissionType>& permissions, const std::shared_ptr<BasicChannel> &channel, std::shared_ptr<CalculateCache> cache, std::shared_ptr<TSServer> server, bool server_defined) {
|
|
||||||
if(!server_defined && !server) server = this->server;
|
|
||||||
|
|
||||||
if(server) return server->calculatePermissions(test, this->getClientDatabaseId(), permissions, this->getType(), channel, cache);
|
|
||||||
deque<pair<permission::PermissionType, permission::PermissionValue>> result;
|
|
||||||
|
|
||||||
/* when you're not bound to any channel cou could only have server group permissions */
|
|
||||||
/* we're loading here all server groups */
|
|
||||||
{
|
|
||||||
auto server_groups = serverInstance->getGroupManager()->getServerGroups(this->getClientDatabaseId(), this->getType());
|
|
||||||
for(const auto& permission : permissions) {
|
|
||||||
permission::PermissionValue value = permNotGranted;
|
|
||||||
|
|
||||||
for(const auto &gr : serverInstance->getGroupManager()->getServerGroups(this->getClientDatabaseId(), this->getType())){
|
|
||||||
auto group_permissions = gr->group->permissions();
|
|
||||||
auto flagged_permissions = group_permissions->permission_value_flagged(permission);
|
|
||||||
if(flagged_permissions.has_value)
|
|
||||||
if(flagged_permissions.value > value || flagged_permissions.value == -1) value = flagged_permissions.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.emplace_back(permission, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
permission::PermissionValue DataClient::getPermissionGrantValue(permission::PermissionTestType test, permission::PermissionType type, const std::shared_ptr<BasicChannel>& target) {
|
|
||||||
permission::PermissionValue result = permNotGranted;
|
|
||||||
|
|
||||||
if(this->server) {
|
|
||||||
return this->server->calculatePermissionGrant(test, this->getClientDatabaseId(), type, this->getType(), target);
|
|
||||||
} else {
|
|
||||||
/* if you're not bound to a channel then you cant be bound to a server as well. */
|
|
||||||
//TODO: Implement negate flag!
|
|
||||||
for(const auto &gr : serverInstance->getGroupManager()->getServerGroups(this->getClientDatabaseId(), this->getType())){
|
|
||||||
auto group_permissions = gr->group->permissions();
|
|
||||||
auto flagged_permissions = group_permissions->permission_granted_flagged(type);
|
|
||||||
if(flagged_permissions.has_value)
|
|
||||||
if(flagged_permissions.value > result || flagged_permissions.value == -1) result = flagged_permissions.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DataClient::permissionGranted(PermissionTestType test, permission::PermissionType type, permission::PermissionValue required, const shared_ptr<BasicChannel>& target, bool force_granted, std::shared_ptr<CalculateCache> cache, std::shared_ptr<TSServer> server, bool server_defined) {
|
|
||||||
auto value = this->permissionValue(test, type, target, cache, server, server_defined);
|
|
||||||
bool result = this->permission_granted(value, required, force_granted);
|
|
||||||
|
|
||||||
#ifdef DEBUG_PERMISSION
|
|
||||||
{
|
|
||||||
auto serverId = 0;
|
|
||||||
auto client = dynamic_cast<ConnectedClient*>(this);
|
|
||||||
if(client)
|
|
||||||
serverId = client->getServerId();
|
|
||||||
debugMessage(serverId, "[Permission] Value test result for test type {}.", test);
|
|
||||||
debugMessage(serverId,
|
|
||||||
"[Permission] Permission: {} Required value: {} Gained value: {} Force required: {} Channel: {} Result: {}",
|
|
||||||
permission::resolvePermissionData(type)->name,
|
|
||||||
required, value, force_granted, (target ? target->name() : "none"), result
|
|
||||||
);
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DataClient::permissionGrantGranted(PermissionTestType test, permission::PermissionType type, permission::PermissionValue required, const shared_ptr<BasicChannel>& target, bool force_granted) {
|
|
||||||
auto value = this->getPermissionGrantValue(test, type, target);
|
|
||||||
bool result = this->permission_granted(value, required, force_granted);
|
|
||||||
|
|
||||||
#ifdef DEBUG_PERMISSION
|
|
||||||
{
|
|
||||||
auto serverId = 0;
|
|
||||||
auto client = dynamic_cast<ConnectedClient*>(this);
|
|
||||||
if(client)
|
|
||||||
serverId = client->getServerId();
|
|
||||||
debugMessage(serverId, "[Permission] Grant test result for test type {}.", test);
|
|
||||||
debugMessage(serverId,
|
|
||||||
"[Permission] Permission: {} Required value: {} Gained value: {} Force required: {} Channel: {} Result: {}",
|
|
||||||
permission::resolvePermissionData(type)->name,
|
|
||||||
required, value, force_granted, (target ? target->name() : "none"), result
|
|
||||||
);
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::shared_ptr<GroupAssignment>> DataClient::assignedServerGroups() {
|
std::vector<std::shared_ptr<GroupAssignment>> DataClient::assignedServerGroups() {
|
||||||
@ -278,4 +184,4 @@ bool DataClient::channelGroupAssigned(const shared_ptr<Group> &group, const shar
|
|||||||
|
|
||||||
std::string DataClient::getAvatarId() {
|
std::string DataClient::getAvatarId() {
|
||||||
return hex::hex(base64::validate(this->getUid()) ? base64::decode(this->getUid()) : this->getUid(), 'a', 'q');
|
return hex::hex(base64::validate(this->getUid()) ? base64::decode(this->getUid()) : this->getUid(), 'a', 'q');
|
||||||
}
|
}
|
||||||
|
@ -57,69 +57,20 @@ namespace ts {
|
|||||||
|
|
||||||
PropertyWrapper properties(){ return { this->_properties }; }
|
PropertyWrapper properties(){ return { this->_properties }; }
|
||||||
|
|
||||||
virtual std::deque<std::pair<permission::PermissionType, permission::PermissionValue>> permissionValues(permission::PermissionTestType test,
|
/* main permission calculate function */
|
||||||
const std::deque<permission::PermissionType>&,
|
permission::v2::PermissionFlaggedValue calculate_permission(
|
||||||
const std::shared_ptr<BasicChannel>& channel = nullptr,
|
permission::PermissionType,
|
||||||
std::shared_ptr<CalculateCache> cache = nullptr,
|
ChannelId channel,
|
||||||
std::shared_ptr<TSServer> server = nullptr,
|
bool granted = false,
|
||||||
bool server_defined = false);
|
std::shared_ptr<CalculateCache> cache = nullptr
|
||||||
inline permission::PermissionValue permissionValue(permission::PermissionType type, const std::shared_ptr<BasicChannel>& targetChannel = nullptr) {
|
|
||||||
return this->permissionValue(permission::PERMTEST_ORDERED, type, targetChannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual permission::PermissionValue permissionValue(permission::PermissionTestType test,
|
|
||||||
permission::PermissionType,
|
|
||||||
const std::shared_ptr<BasicChannel>& channel = nullptr,
|
|
||||||
std::shared_ptr<CalculateCache> cache = nullptr,
|
|
||||||
std::shared_ptr<TSServer> server = nullptr,
|
|
||||||
bool server_defined = false);
|
|
||||||
|
|
||||||
virtual permission::v2::PermissionFlaggedValue permissionValueFlagged(
|
|
||||||
permission::PermissionType,
|
|
||||||
const std::shared_ptr<BasicChannel>& channel = nullptr,
|
|
||||||
std::shared_ptr<CalculateCache> cache = nullptr,
|
|
||||||
std::shared_ptr<TSServer> server = nullptr,
|
|
||||||
bool server_defined = false
|
|
||||||
);
|
);
|
||||||
|
|
||||||
virtual bool permissionGranted(permission::PermissionTestType test,
|
std::vector<std::pair<permission::PermissionType, permission::v2::PermissionFlaggedValue>> calculate_permissions(
|
||||||
permission::PermissionType,
|
const std::deque<permission::PermissionType>&,
|
||||||
permission::PermissionValue,
|
ChannelId channel,
|
||||||
const std::shared_ptr<BasicChannel>& channel = nullptr,
|
bool granted = false,
|
||||||
bool required = true,
|
std::shared_ptr<CalculateCache> cache = nullptr
|
||||||
std::shared_ptr<CalculateCache> cache = nullptr,
|
);
|
||||||
std::shared_ptr<TSServer> server = nullptr,
|
|
||||||
bool server_defined = false);
|
|
||||||
|
|
||||||
inline permission::PermissionValue getPermissionGrantValue(permission::PermissionType type, const std::shared_ptr<BasicChannel>& targetChannel = nullptr) {
|
|
||||||
return this->getPermissionGrantValue(permission::PERMTEST_ORDERED, type, targetChannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline bool permission_granted(T, permission::PermissionValue, bool = false) = delete; /* only permission values */
|
|
||||||
[[deprecated]] __always_inline bool permission_granted(ts::permission::PermissionValue value, ts::permission::PermissionValue required, bool enforce_required = true) {
|
|
||||||
return DataClient::permission_granted({value, value != permNotGranted}, required, enforce_required);
|
|
||||||
}
|
|
||||||
|
|
||||||
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> &);
|
||||||
@ -153,6 +104,8 @@ namespace ts {
|
|||||||
|
|
||||||
std::shared_ptr<permission::v2::PermissionManager> clientPermissions = nullptr;
|
std::shared_ptr<permission::v2::PermissionManager> clientPermissions = nullptr;
|
||||||
std::shared_ptr<Properties> _properties;
|
std::shared_ptr<Properties> _properties;
|
||||||
|
|
||||||
|
std::shared_ptr<BasicChannel> currentChannel = nullptr;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -22,9 +22,8 @@ InternalClient::~InternalClient() {
|
|||||||
memtrack::freed<InternalClient>(this);
|
memtrack::freed<InternalClient>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InternalClient::sendCommand(const ts::Command &command, bool low) {
|
void InternalClient::sendCommand(const ts::Command &command, bool low) { }
|
||||||
|
void InternalClient::sendCommand(const ts::command_builder &command, bool low) { }
|
||||||
}
|
|
||||||
|
|
||||||
bool InternalClient::closeConnection(const std::chrono::system_clock::time_point& timeout) {
|
bool InternalClient::closeConnection(const std::chrono::system_clock::time_point& timeout) {
|
||||||
logError(this->getServerId(), "Internal client is force to disconnect?");
|
logError(this->getServerId(), "Internal client is force to disconnect?");
|
||||||
|
@ -15,6 +15,7 @@ namespace ts {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void sendCommand(const ts::Command &command, bool low) override;
|
void sendCommand(const ts::Command &command, bool low) override;
|
||||||
|
void sendCommand(const ts::command_builder &command, bool low) override;
|
||||||
bool closeConnection(const std::chrono::system_clock::time_point& timeout = std::chrono::system_clock::time_point()) override;
|
bool closeConnection(const std::chrono::system_clock::time_point& timeout = std::chrono::system_clock::time_point()) override;
|
||||||
bool disconnect(const std::string &reason) override;
|
bool disconnect(const std::string &reason) override;
|
||||||
protected:
|
protected:
|
||||||
|
@ -39,12 +39,7 @@ bool SpeakingClient::shouldReceiveVoiceWhisper(const std::shared_ptr<ConnectedCl
|
|||||||
if(!this->shouldReceiveVoice(sender))
|
if(!this->shouldReceiveVoice(sender))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto required_permission = this->cached_permission_value(permission::i_client_needed_whisper_power);
|
return permission::v2::permission_granted(this->cpmerission_needed_whisper_power, sender->cpmerission_whisper_power);
|
||||||
if(required_permission == permNotGranted)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
auto granted_permission = sender->cached_permission_value(permission::i_client_whisper_power);
|
|
||||||
return granted_permission >= required_permission;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpeakingClient::handlePacketVoice(const pipes::buffer_view& data, bool head, bool fragmented) {
|
void SpeakingClient::handlePacketVoice(const pipes::buffer_view& data, bool head, bool fragmented) {
|
||||||
@ -445,7 +440,7 @@ command_result SpeakingClient::handleCommandClientInit(Command& cmd) {
|
|||||||
debugMessage(this->getServerId(), "{} Got client init. (HWID: {})", CLIENT_STR_LOG_PREFIX, this->getHardwareId());
|
debugMessage(this->getServerId(), "{} Got client init. (HWID: {})", CLIENT_STR_LOG_PREFIX, this->getHardwareId());
|
||||||
TIMING_STEP(timings, "props apply");
|
TIMING_STEP(timings, "props apply");
|
||||||
|
|
||||||
auto permissions_list = this->permissionValues(permission::PERMTEST_ORDERED, {
|
auto permissions_list = this->calculate_permissions({
|
||||||
permission::b_virtualserver_join_ignore_password,
|
permission::b_virtualserver_join_ignore_password,
|
||||||
permission::b_client_ignore_bans,
|
permission::b_client_ignore_bans,
|
||||||
permission::b_client_ignore_vpn,
|
permission::b_client_ignore_vpn,
|
||||||
@ -457,17 +452,17 @@ command_result SpeakingClient::handleCommandClientInit(Command& cmd) {
|
|||||||
permission::b_client_enforce_valid_hwid,
|
permission::b_client_enforce_valid_hwid,
|
||||||
|
|
||||||
permission::b_client_use_reserved_slot
|
permission::b_client_use_reserved_slot
|
||||||
}, nullptr);
|
}, 0);
|
||||||
auto permissions = map<permission::PermissionType, permission::PermissionValue>(permissions_list.begin(), permissions_list.end());
|
auto permissions = map<permission::PermissionType, permission::v2::PermissionFlaggedValue>(permissions_list.begin(), permissions_list.end());
|
||||||
TIMING_STEP(timings, "perm calc 1");
|
TIMING_STEP(timings, "perm calc 1");
|
||||||
|
|
||||||
if(geoloc::provider_vpn && permissions[permission::b_client_ignore_vpn] == permNotGranted) {
|
if(geoloc::provider_vpn && !permission::v2::permission_granted(1, permissions[permission::b_client_ignore_vpn])) {
|
||||||
auto provider = this->isAddressV4() ? geoloc::provider_vpn->resolveInfoV4(this->getPeerIp(), true) : geoloc::provider_vpn->resolveInfoV6(this->getPeerIp(), true);
|
auto provider = this->isAddressV4() ? geoloc::provider_vpn->resolveInfoV4(this->getPeerIp(), true) : geoloc::provider_vpn->resolveInfoV6(this->getPeerIp(), true);
|
||||||
if(provider)
|
if(provider)
|
||||||
return command_result{error::server_connect_banned, strvar::transform(ts::config::messages::kick_vpn, strvar::StringValue{"provider.name", provider->name}, strvar::StringValue{"provider.website", provider->side})};
|
return command_result{error::server_connect_banned, strvar::transform(ts::config::messages::kick_vpn, strvar::StringValue{"provider.name", provider->name}, strvar::StringValue{"provider.website", provider->side})};
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this->getType() == ClientType::CLIENT_TEAMSPEAK && (permissions[permission::b_client_enforce_valid_hwid] == permNotGranted && permissions[permission::b_client_enforce_valid_hwid] == 0)) {
|
if(this->getType() == ClientType::CLIENT_TEAMSPEAK && permission::v2::permission_granted(1, permissions[permission::b_client_enforce_valid_hwid])) {
|
||||||
auto hwid = this->properties()[property::CLIENT_HARDWARE_ID].as<string>();
|
auto hwid = this->properties()[property::CLIENT_HARDWARE_ID].as<string>();
|
||||||
if(
|
if(
|
||||||
!std::regex_match(hwid, regex_hwid_windows) &&
|
!std::regex_match(hwid, regex_hwid_windows) &&
|
||||||
@ -480,8 +475,7 @@ command_result SpeakingClient::handleCommandClientInit(Command& cmd) {
|
|||||||
}
|
}
|
||||||
TIMING_STEP(timings, "valid hw ip");
|
TIMING_STEP(timings, "valid hw ip");
|
||||||
|
|
||||||
auto ignorePassword = permissions[permission::b_virtualserver_join_ignore_password] > 0 && permissions[permission::b_virtualserver_join_ignore_password] != permNotGranted;
|
if(!permission::v2::permission_granted(1, permissions[permission::b_virtualserver_join_ignore_password]))
|
||||||
if(!ignorePassword)
|
|
||||||
if(!this->server->verifyServerPassword(cmd["client_server_password"].string(), true))
|
if(!this->server->verifyServerPassword(cmd["client_server_password"].string(), true))
|
||||||
return command_result{error::server_invalid_password};
|
return command_result{error::server_invalid_password};
|
||||||
|
|
||||||
@ -500,17 +494,17 @@ command_result SpeakingClient::handleCommandClientInit(Command& cmd) {
|
|||||||
clones_hwid++;
|
clones_hwid++;
|
||||||
});
|
});
|
||||||
|
|
||||||
if(permissions[permission::i_client_max_clones_uid] > 0 && clones_uid >= permissions[permission::i_client_max_clones_uid]) {
|
if(clones_uid > 0 && permissions[permission::i_client_max_clones_uid].has_value && !permission::v2::permission_granted(clones_uid, permissions[permission::i_client_max_clones_uid])) {
|
||||||
logMessage(this->getServerId(), "{} Disconnecting because there are already {} uid clones connected. (Allowed: {})", CLIENT_STR_LOG_PREFIX, clones_uid, permissions[permission::i_client_max_clones_uid]);
|
logMessage(this->getServerId(), "{} Disconnecting because there are already {} uid clones connected. (Allowed: {})", CLIENT_STR_LOG_PREFIX, clones_uid, permissions[permission::i_client_max_clones_uid]);
|
||||||
return command_result{error:: client_too_many_clones_connected, "too many clones connected (uid)"};
|
return command_result{error:: client_too_many_clones_connected, "too many clones connected (uid)"};
|
||||||
}
|
}
|
||||||
|
|
||||||
if(permissions[permission::i_client_max_clones_ip] > 0 && clones_ip >= permissions[permission::i_client_max_clones_ip]) {
|
if(clones_ip > 0 && permissions[permission::i_client_max_clones_ip].has_value && !permission::v2::permission_granted(clones_ip, permissions[permission::i_client_max_clones_ip])) {
|
||||||
logMessage(this->getServerId(), "{} Disconnecting because there are already {} ip clones connected. (Allowed: {})", CLIENT_STR_LOG_PREFIX, clones_ip, permissions[permission::i_client_max_clones_ip]);
|
logMessage(this->getServerId(), "{} Disconnecting because there are already {} ip clones connected. (Allowed: {})", CLIENT_STR_LOG_PREFIX, clones_ip, permissions[permission::i_client_max_clones_ip]);
|
||||||
return command_result{error:: client_too_many_clones_connected, "too many clones connected (ip)"};
|
return command_result{error:: client_too_many_clones_connected, "too many clones connected (ip)"};
|
||||||
}
|
}
|
||||||
|
|
||||||
if(permissions[permission::i_client_max_clones_hwid] > 0 && clones_hwid >= permissions[permission::i_client_max_clones_hwid] && !_own_hwid.empty()) {
|
if(clones_hwid > 0 && permissions[permission::i_client_max_clones_hwid].has_value && !permission::v2::permission_granted(clones_hwid, permissions[permission::i_client_max_clones_hwid])) {
|
||||||
logMessage(this->getServerId(), "{} Disconnecting because there are already {} hwid clones connected. (Allowed: {})", CLIENT_STR_LOG_PREFIX, clones_hwid, permissions[permission::i_client_max_clones_hwid]);
|
logMessage(this->getServerId(), "{} Disconnecting because there are already {} hwid clones connected. (Allowed: {})", CLIENT_STR_LOG_PREFIX, clones_hwid, permissions[permission::i_client_max_clones_hwid]);
|
||||||
return command_result{error:: client_too_many_clones_connected, "too many clones connected (hwid)"};
|
return command_result{error:: client_too_many_clones_connected, "too many clones connected (hwid)"};
|
||||||
}
|
}
|
||||||
@ -581,7 +575,7 @@ command_result SpeakingClient::handleCommandClientInit(Command& cmd) {
|
|||||||
auto maxClients = this->server->properties()[property::VIRTUALSERVER_MAXCLIENTS].as<size_t>();
|
auto maxClients = this->server->properties()[property::VIRTUALSERVER_MAXCLIENTS].as<size_t>();
|
||||||
auto reserved = this->server->properties()[property::VIRTUALSERVER_RESERVED_SLOTS].as<size_t>();
|
auto reserved = this->server->properties()[property::VIRTUALSERVER_RESERVED_SLOTS].as<size_t>();
|
||||||
|
|
||||||
bool allowReserved = permissions[permission::b_client_use_reserved_slot] != permNotGranted && permissions[permission::b_client_use_reserved_slot] != 0;
|
bool allowReserved = permission::v2::permission_granted(1, permissions[permission::b_client_use_reserved_slot]);
|
||||||
if(reserved > maxClients){
|
if(reserved > maxClients){
|
||||||
if(!allowReserved)
|
if(!allowReserved)
|
||||||
return command_result{error::server_maxclients_reached};
|
return command_result{error::server_maxclients_reached};
|
||||||
@ -782,7 +776,7 @@ void SpeakingClient::tick(const std::chrono::system_clock::time_point &time) {
|
|||||||
|
|
||||||
void SpeakingClient::updateChannelClientProperties(bool channel_lock, bool notify) {
|
void SpeakingClient::updateChannelClientProperties(bool channel_lock, bool notify) {
|
||||||
ConnectedClient::updateChannelClientProperties(channel_lock, notify);
|
ConnectedClient::updateChannelClientProperties(channel_lock, notify);
|
||||||
this->max_idle_time = this->permissionValueFlagged(permission::i_client_max_idletime, this->currentChannel);
|
this->max_idle_time = this->calculate_permission(permission::i_client_max_idletime, this->currentChannel ? this->currentChannel->channelId() : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
command_result SpeakingClient::handleCommand(Command &command) {
|
command_result SpeakingClient::handleCommand(Command &command) {
|
||||||
|
1900
server/src/client/command_handler/channel.cpp
Normal file
1900
server/src/client/command_handler/channel.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1214
server/src/client/command_handler/client.cpp
Normal file
1214
server/src/client/command_handler/client.cpp
Normal file
File diff suppressed because it is too large
Load Diff
486
server/src/client/command_handler/file.cpp
Normal file
486
server/src/client/command_handler/file.cpp
Normal file
@ -0,0 +1,486 @@
|
|||||||
|
//
|
||||||
|
// Created by wolverindev on 26.01.20.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <spdlog/sinks/rotating_file_sink.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <bitset>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
#include "../../build.h"
|
||||||
|
#include "../ConnectedClient.h"
|
||||||
|
#include "../InternalClient.h"
|
||||||
|
#include "../../server/file/FileServer.h"
|
||||||
|
#include "../../server/VoiceServer.h"
|
||||||
|
#include "../voice/VoiceClient.h"
|
||||||
|
#include "PermissionManager.h"
|
||||||
|
#include "../../InstanceHandler.h"
|
||||||
|
#include "../../server/QueryServer.h"
|
||||||
|
#include "../file/FileClient.h"
|
||||||
|
#include "../music/MusicClient.h"
|
||||||
|
#include "../query/QueryClient.h"
|
||||||
|
#include "../../weblist/WebListManager.h"
|
||||||
|
#include "../../manager/ConversationManager.h"
|
||||||
|
#include "../../manager/PermissionNameMapper.h"
|
||||||
|
#include <experimental/filesystem>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <StringVariable.h>
|
||||||
|
|
||||||
|
#include "helpers.h"
|
||||||
|
|
||||||
|
#include <Properties.h>
|
||||||
|
#include <log/LogUtils.h>
|
||||||
|
#include <misc/sassert.h>
|
||||||
|
#include <misc/base64.h>
|
||||||
|
#include <misc/hex.h>
|
||||||
|
#include <misc/digest.h>
|
||||||
|
#include <misc/rnd.h>
|
||||||
|
#include <misc/timer.h>
|
||||||
|
#include <misc/strobf.h>
|
||||||
|
#include <misc/scope_guard.h>
|
||||||
|
#include <bbcode/bbcodes.h>
|
||||||
|
|
||||||
|
namespace fs = std::experimental::filesystem;
|
||||||
|
using namespace std::chrono;
|
||||||
|
using namespace std;
|
||||||
|
using namespace ts;
|
||||||
|
using namespace ts::server;
|
||||||
|
using namespace ts::token;
|
||||||
|
|
||||||
|
#define QUERY_PASSWORD_LENGTH 12
|
||||||
|
|
||||||
|
//ftgetfilelist cid=1 cpw path=\/ return_code=1:x
|
||||||
|
//Answer:
|
||||||
|
//1 .. n
|
||||||
|
// notifyfilelist cid=1 path=\/ return_code=1:x name=testFile size=35256 datetime=1509459767 type=1|name=testDir size=0 datetime=1509459741 type=0|name=testDir_2 size=0 datetime=1509459763 type=0
|
||||||
|
//notifyfilelistfinished cid=1 path=\/
|
||||||
|
inline void cmd_filelist_append_files(ServerId sid, Command &command, vector<std::shared_ptr<file::FileEntry>> files) {
|
||||||
|
int index = 0;
|
||||||
|
|
||||||
|
logTrace(sid, "Sending file list for path {}", command["path"].string());
|
||||||
|
for (const auto& fileEntry : files) {
|
||||||
|
logTrace(sid, " - {} ({})", fileEntry->name, fileEntry->type == file::FileType::FILE ? "file" : "directory");
|
||||||
|
|
||||||
|
command[index]["name"] = fileEntry->name;
|
||||||
|
command[index]["datetime"] = std::chrono::duration_cast<std::chrono::seconds>(fileEntry->lastChanged.time_since_epoch()).count();
|
||||||
|
command[index]["type"] = fileEntry->type;
|
||||||
|
if (fileEntry->type == file::FileType::FILE)
|
||||||
|
command[index]["size"] = static_pointer_cast<file::File>(fileEntry)->fileSize;
|
||||||
|
else
|
||||||
|
command[index]["size"] = 0;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CMD_REQ_FSERVER if(!serverInstance->getFileServer()) return command_result{error::vs_critical, "file server not started yet!"}
|
||||||
|
|
||||||
|
command_result ConnectedClient::handleCommandFTGetFileList(Command &cmd) {
|
||||||
|
CMD_REQ_SERVER;
|
||||||
|
CMD_RESET_IDLE;
|
||||||
|
CMD_REQ_FSERVER;
|
||||||
|
std::string code = cmd["return_code"].size() > 0 ? cmd["return_code"].string() : "";
|
||||||
|
|
||||||
|
Command fileList(this->getExternalType() == CLIENT_TEAMSPEAK ? "notifyfilelist" : "");
|
||||||
|
Command fileListFinished("notifyfilelistfinished");
|
||||||
|
|
||||||
|
fileList["path"] = cmd["path"].as<std::string>();
|
||||||
|
if(!code.empty()) fileList["return_code"] = code;
|
||||||
|
fileListFinished["path"] = cmd["path"].as<std::string>();
|
||||||
|
fileList["cid"] = cmd["cid"].as<size_t>();
|
||||||
|
fileListFinished["cid"] = cmd["cid"].as<ChannelId>();
|
||||||
|
|
||||||
|
if (cmd[0].has("cid") && cmd["cid"] != 0) { //Channel
|
||||||
|
auto channel = this->server->channelTree->findChannel(cmd["cid"].as<ChannelId>());
|
||||||
|
if (!channel) return command_result{error::channel_invalid_id, "Cant resolve channel"};
|
||||||
|
if (!channel->passwordMatch(cmd["cpw"]) && !permission::v2::permission_granted(1, this->calculate_permission(permission::b_ft_ignore_password, channel->channelId())))
|
||||||
|
return cmd["cpw"].string().empty() ? command_result{permission::b_ft_ignore_password} : command_result{error::channel_invalid_password};
|
||||||
|
ACTION_REQUIRES_CHANNEL_PERMISSION(channel, permission::i_ft_needed_file_browse_power, permission::i_ft_file_browse_power, true);
|
||||||
|
|
||||||
|
cmd_filelist_append_files(
|
||||||
|
this->getServerId(),
|
||||||
|
fileList,
|
||||||
|
serverInstance->getFileServer()->listFiles(serverInstance->getFileServer()->resolveDirectory(this->server, channel, cmd["path"].as<std::string>()))
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if (cmd["path"].as<string>() == "/icons" || cmd["path"].as<string>() == "/icons/") {
|
||||||
|
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_icon_manage, 1);
|
||||||
|
cmd_filelist_append_files(this->getServerId(), fileList, serverInstance->getFileServer()->listFiles(serverInstance->getFileServer()->iconDirectory(this->server)));
|
||||||
|
} else if (cmd["path"].as<string>() == "/") {
|
||||||
|
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_icon_manage, 1);
|
||||||
|
cmd_filelist_append_files(this->getServerId(), fileList, serverInstance->getFileServer()->listFiles(serverInstance->getFileServer()->avatarDirectory(this->server)));
|
||||||
|
} else {
|
||||||
|
logMessage(this->getServerId(), "{} Requested file list for unknown path/name: path: {} name: {}", cmd["path"].string(), cmd["name"].string());
|
||||||
|
return command_result{error::not_implemented};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileList[0].has("name")) {
|
||||||
|
if(dynamic_cast<VoiceClient*>(this)) {
|
||||||
|
dynamic_cast<VoiceClient*>(this)->sendCommand0(fileList.build(), false, true); /* We need to process this directly else the order could get shuffled up! */
|
||||||
|
this->sendCommand(fileListFinished);
|
||||||
|
} else {
|
||||||
|
this->sendCommand(fileList);
|
||||||
|
if(this->getType() != CLIENT_QUERY)
|
||||||
|
this->sendCommand(fileListFinished);
|
||||||
|
}
|
||||||
|
return command_result{error::ok};
|
||||||
|
} else {
|
||||||
|
return command_result{error::database_empty_result};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//ftcreatedir cid=4 cpw dirname=\/TestDir return_code=1:17
|
||||||
|
command_result ConnectedClient::handleCommandFTCreateDir(Command &cmd) {
|
||||||
|
CMD_REQ_SERVER;
|
||||||
|
CMD_CHK_AND_INC_FLOOD_POINTS(5);
|
||||||
|
CMD_REQ_FSERVER;
|
||||||
|
|
||||||
|
auto channel = this->server->channelTree->findChannel(cmd["cid"].as<ChannelId>());
|
||||||
|
if (!channel) return command_result{error::channel_invalid_id, "Cant resolve channel"};
|
||||||
|
if (!channel->passwordMatch(cmd["cpw"]) && !permission::v2::permission_granted(1, this->calculate_permission(permission::b_ft_ignore_password, channel->channelId())))
|
||||||
|
return cmd["cpw"].string().empty() ? command_result{permission::b_ft_ignore_password} : command_result{error::channel_invalid_password};
|
||||||
|
ACTION_REQUIRES_CHANNEL_PERMISSION(channel, permission::i_ft_needed_directory_create_power, permission::i_ft_directory_create_power, true);
|
||||||
|
|
||||||
|
auto dir = serverInstance->getFileServer()->createDirectory(cmd["dirname"], serverInstance->getFileServer()->resolveDirectory(this->server, channel, cmd["path"].as<std::string>()));
|
||||||
|
if (!dir) return command_result{error::file_invalid_path, "could not create dir"};
|
||||||
|
|
||||||
|
return command_result{error::ok};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
command_result ConnectedClient::handleCommandFTDeleteFile(Command &cmd) {
|
||||||
|
CMD_REQ_SERVER;
|
||||||
|
CMD_CHK_AND_INC_FLOOD_POINTS(5);
|
||||||
|
CMD_REQ_FSERVER;
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<file::FileEntry>> files;
|
||||||
|
|
||||||
|
if (cmd[0].has("cid") && cmd["cid"] != 0) { //Channel
|
||||||
|
auto channel = this->server->channelTree->findChannel(cmd["cid"].as<ChannelId>());
|
||||||
|
if (!channel) return command_result{error::channel_invalid_id, "Cant resolve channel"};
|
||||||
|
if (!channel->passwordMatch(cmd["cpw"]) && !permission::v2::permission_granted(1, this->calculate_permission(permission::b_ft_ignore_password, channel->channelId())))
|
||||||
|
return cmd["cpw"].string().empty() ? command_result{permission::b_ft_ignore_password} : command_result{error::channel_invalid_password};
|
||||||
|
ACTION_REQUIRES_CHANNEL_PERMISSION(channel, permission::i_ft_needed_file_delete_power, permission::i_ft_file_delete_power, true);
|
||||||
|
|
||||||
|
for (int index = 0; index < cmd.bulkCount(); index++)
|
||||||
|
files.push_back(serverInstance->getFileServer()->findFile(cmd[index]["name"].as<std::string>(), serverInstance->getFileServer()->resolveDirectory(this->server, channel)));
|
||||||
|
} else {
|
||||||
|
if (cmd["name"].string().find("/icon_") == 0 && cmd["path"].string().empty()) {
|
||||||
|
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_icon_manage, 1);
|
||||||
|
files.push_back(serverInstance->getFileServer()->findFile(cmd["name"].string(), serverInstance->getFileServer()->iconDirectory(this->server)));
|
||||||
|
} else if (cmd["name"].string().find("/avatar_") == 0 && cmd["path"].string().empty()) {
|
||||||
|
if (cmd["name"].string() != "/avatar_") {
|
||||||
|
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_client_avatar_delete_other, 1);
|
||||||
|
|
||||||
|
auto uid = cmd["name"].string().substr(strlen("/avatar_"));
|
||||||
|
auto avId = hex::hex(base64::decode(uid), 'a', 'q');
|
||||||
|
|
||||||
|
auto cls = this->server->findClientsByUid(uid);
|
||||||
|
for (const auto &cl : cls) {
|
||||||
|
cl->properties()[property::CLIENT_FLAG_AVATAR] = "";
|
||||||
|
this->server->notifyClientPropertyUpdates(cl, deque<property::ClientProperties>{property::CLIENT_FLAG_AVATAR});
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd["name"] = "/avatar_" + avId;
|
||||||
|
} else {
|
||||||
|
cmd["name"] = "/avatar_" + this->getAvatarId();
|
||||||
|
this->properties()[property::CLIENT_FLAG_AVATAR] = "";
|
||||||
|
this->server->notifyClientPropertyUpdates(_this.lock(), deque<property::ClientProperties>{property::CLIENT_FLAG_AVATAR});
|
||||||
|
}
|
||||||
|
files.push_back(serverInstance->getFileServer()->findFile(cmd["name"].string(), serverInstance->getFileServer()->avatarDirectory(this->server)));
|
||||||
|
} else {
|
||||||
|
logError(this->getServerId(), "Unknown requested file to delete: {}", cmd["path"].as<std::string>());
|
||||||
|
return command_result{error::not_implemented};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &file : files) {
|
||||||
|
if (!file) continue;
|
||||||
|
if (!serverInstance->getFileServer()->deleteFile(file)) {
|
||||||
|
logCritical(this->getServerId(), "Could not delete file {}/{}", file->path, file->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return command_result{error::ok};
|
||||||
|
}
|
||||||
|
|
||||||
|
command_result ConnectedClient::handleCommandFTInitUpload(Command &cmd) {
|
||||||
|
CMD_REQ_SERVER;
|
||||||
|
CMD_REQ_FSERVER;
|
||||||
|
|
||||||
|
std::shared_ptr<file::Directory> directory = nullptr;
|
||||||
|
|
||||||
|
if (cmd[0].has("cid") && cmd["cid"] != 0) { //Channel
|
||||||
|
auto channel = this->server->channelTree->findChannel(cmd["cid"].as<ChannelId>());
|
||||||
|
if (!channel) return command_result{error::channel_invalid_id, "Cant resolve channel"};
|
||||||
|
if (!channel->passwordMatch(cmd["cpw"]) && !permission::v2::permission_granted(1, this->calculate_permission(permission::b_ft_ignore_password, channel->channelId())))
|
||||||
|
return cmd["cpw"].string().empty() ? command_result{permission::b_ft_ignore_password} : command_result{error::channel_invalid_password};
|
||||||
|
ACTION_REQUIRES_CHANNEL_PERMISSION(channel, permission::i_ft_needed_file_upload_power, permission::i_ft_file_upload_power, true);
|
||||||
|
directory = serverInstance->getFileServer()->resolveDirectory(this->server, channel);
|
||||||
|
} else {
|
||||||
|
if (cmd["path"].as<std::string>().empty() && cmd["name"].as<std::string>().find("/icon_") == 0) {
|
||||||
|
auto max_size = this->calculate_permission(permission::i_max_icon_filesize, 0);
|
||||||
|
if(max_size.has_value && !max_size.has_infinite_power() && (max_size.value < 0 || max_size.value < cmd["size"].as<size_t>()))
|
||||||
|
return command_result{permission::i_max_icon_filesize};
|
||||||
|
directory = serverInstance->getFileServer()->iconDirectory(this->server);
|
||||||
|
} else if (cmd["path"].as<std::string>().empty() && cmd["name"].string() == "/avatar") {
|
||||||
|
auto max_size = this->calculate_permission(permission::i_client_max_avatar_filesize, 0);
|
||||||
|
if(max_size.has_value && !max_size.has_infinite_power() && (max_size.value < 0 || max_size.value < cmd["size"].as<size_t>()))
|
||||||
|
return command_result{permission::i_client_max_avatar_filesize};
|
||||||
|
|
||||||
|
directory = serverInstance->getFileServer()->avatarDirectory(this->server);
|
||||||
|
cmd["name"] = "/avatar_" + this->getAvatarId();
|
||||||
|
} else {
|
||||||
|
cerr << "Unknown requested directory: " << cmd["path"].as<std::string>() << endl;
|
||||||
|
return command_result{error::not_implemented};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!directory || directory->type != file::FileType::DIRECTORY) { //Should not happen
|
||||||
|
cerr << "Invalid upload file path!" << endl;
|
||||||
|
return command_result{error::file_invalid_path, "could not resolve directory"};
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto server_quota = this->server->properties()[property::VIRTUALSERVER_UPLOAD_QUOTA].as<ssize_t>();
|
||||||
|
auto server_used_quota = this->server->properties()[property::VIRTUALSERVER_MONTH_BYTES_UPLOADED].as<size_t>();
|
||||||
|
server_used_quota += cmd["size"].as<uint64_t>();
|
||||||
|
for(const auto& trans : serverInstance->getFileServer()->pending_file_transfers())
|
||||||
|
server_used_quota += trans->size;
|
||||||
|
for(const auto& trans : serverInstance->getFileServer()->running_file_transfers())
|
||||||
|
server_used_quota += trans->remaining_bytes();
|
||||||
|
if(server_quota >= 0 && server_quota * 1024 * 1024 < (int64_t) server_used_quota) return command_result{error::file_transfer_server_quota_exceeded};
|
||||||
|
|
||||||
|
auto client_quota = this->calculate_permission(permission::i_ft_quota_mb_upload_per_client, 0);
|
||||||
|
auto client_used_quota = this->properties()[property::CLIENT_MONTH_BYTES_UPLOADED].as<size_t>();
|
||||||
|
client_used_quota += cmd["size"].as<uint64_t>();
|
||||||
|
for(const auto& trans : serverInstance->getFileServer()->pending_file_transfers(_this.lock()))
|
||||||
|
client_used_quota += trans->size;
|
||||||
|
for(const auto& trans : serverInstance->getFileServer()->running_file_transfers(_this.lock()))
|
||||||
|
client_used_quota += trans->remaining_bytes();
|
||||||
|
|
||||||
|
if(client_quota.has_value && !client_quota.has_infinite_power() && (client_quota.value < 0 || client_quota.value * 1024 * 1024 < (int64_t) client_used_quota))
|
||||||
|
return command_result{error::file_transfer_client_quota_exceeded};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd["overwrite"].as<bool>() && cmd["resume"].as<bool>()) return command_result{error::file_overwrite_excludes_resume};
|
||||||
|
if (serverInstance->getFileServer()->findFile(cmd["name"].as<std::string>(), directory) && !(cmd["overwrite"].as<bool>() || cmd["resume"].as<bool>()))
|
||||||
|
return command_result{error::file_already_exists, "file already exists"};
|
||||||
|
|
||||||
|
//Request: clientftfid=1 serverftfid=6 ftkey=itRNdsIOvcBiBg\/Xj4Ge51ZSrsShHuid port=30033 seekpos=0
|
||||||
|
//Reqpose: notifystartupload clientftfid=4079 serverftfid=1 ftkey=aX9CFQbfaddHpOYxhQiSLu\/BumfVtPyP port=30033 seekpos=0 proto=1
|
||||||
|
string error = "success";
|
||||||
|
auto key = serverInstance->getFileServer()->generateUploadTransferKey(error, directory->path + "/" + directory->name + cmd["name"].string(), cmd["size"].as<uint64_t>(), 0, _this.lock()); //TODO implement resume!
|
||||||
|
if (!key) return command_result{error::vs_critical};
|
||||||
|
|
||||||
|
Command result(this->getExternalType() == CLIENT_TEAMSPEAK ? "notifystartupload" : "");
|
||||||
|
result["clientftfid"] = cmd["clientftfid"].as<uint64_t>();
|
||||||
|
result["ftkey"] = key->key;
|
||||||
|
|
||||||
|
auto bindings = serverInstance->getFileServer()->list_bindings();
|
||||||
|
if(!bindings.empty()) {
|
||||||
|
result["port"] = net::port(bindings[0]->address);
|
||||||
|
string ip = "";
|
||||||
|
for(auto& entry : bindings) {
|
||||||
|
if(net::is_anybind(entry->address)) {
|
||||||
|
ip = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ip += net::to_string(entry->address, false) + ",";
|
||||||
|
}
|
||||||
|
if(!ip.empty())
|
||||||
|
result["ip"] = ip;
|
||||||
|
} else {
|
||||||
|
return command_result{error::server_is_not_running, "file server is not bound to any address"};
|
||||||
|
}
|
||||||
|
result["seekpos"] = 0;
|
||||||
|
result["proto"] = 1;
|
||||||
|
result["serverftfid"] = key->key_id; //TODO generate!
|
||||||
|
this->sendCommand(result);
|
||||||
|
|
||||||
|
return command_result{error::ok};
|
||||||
|
}
|
||||||
|
|
||||||
|
command_result ConnectedClient::handleCommandFTInitDownload(Command &cmd) {
|
||||||
|
CMD_REQ_SERVER;
|
||||||
|
CMD_REQ_FSERVER;
|
||||||
|
|
||||||
|
std::shared_ptr<file::Directory> directory = nullptr;
|
||||||
|
|
||||||
|
if(!cmd[0].has("path")) cmd["path"] = "";
|
||||||
|
|
||||||
|
if (cmd[0].has("cid") && cmd["cid"] != (ChannelId) 0) { //Channel
|
||||||
|
auto channel = this->server->channelTree->findChannel(cmd["cid"].as<ChannelId>());
|
||||||
|
if (!channel) return command_result{error::channel_invalid_id, "Cant resolve channel"};
|
||||||
|
|
||||||
|
if (!channel->passwordMatch(cmd["cpw"]) && !permission::v2::permission_granted(1, this->calculate_permission(permission::b_ft_ignore_password, channel->channelId())))
|
||||||
|
return cmd["cpw"].string().empty() ? command_result{permission::b_ft_ignore_password} : command_result{error::channel_invalid_password};
|
||||||
|
ACTION_REQUIRES_CHANNEL_PERMISSION(channel, permission::i_ft_needed_file_download_power, permission::i_ft_file_download_power, true);
|
||||||
|
|
||||||
|
directory = serverInstance->getFileServer()->resolveDirectory(this->server, channel);
|
||||||
|
} else {
|
||||||
|
if (cmd["path"].as<std::string>().empty() && cmd["name"].as<std::string>().find("/icon_") == 0) {
|
||||||
|
directory = serverInstance->getFileServer()->iconDirectory(this->server);
|
||||||
|
} else if (cmd["path"].as<std::string>().empty() && cmd["name"].as<std::string>().find("/avatar_") == 0) { //TODO fix avatar download not working
|
||||||
|
directory = serverInstance->getFileServer()->avatarDirectory(this->server);
|
||||||
|
} else {
|
||||||
|
cerr << "Unknown requested directory: " << cmd["path"].as<std::string>() << endl;
|
||||||
|
return command_result{error::not_implemented};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!directory || directory->type != file::FileType::DIRECTORY) { //Should not happen
|
||||||
|
cerr << "Invalid download file path!" << endl;
|
||||||
|
return command_result{error::file_invalid_path, "could not resolve directory"};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!serverInstance->getFileServer()->findFile(cmd["name"].as<std::string>(), directory))
|
||||||
|
return command_result{error::file_not_found, "file not exists"};
|
||||||
|
|
||||||
|
string error = "success";
|
||||||
|
auto key = serverInstance->getFileServer()->generateDownloadTransferKey(error, directory->path + "/" + directory->name + cmd["name"].as<std::string>(), 0, _this.lock()); //TODO implement resume!
|
||||||
|
if (!key) return command_result{error::vs_critical, "cant generate key (" + error + ")"};
|
||||||
|
|
||||||
|
{
|
||||||
|
auto server_quota = this->server->properties()[property::VIRTUALSERVER_DOWNLOAD_QUOTA].as<ssize_t>();
|
||||||
|
auto server_used_quota = this->server->properties()[property::VIRTUALSERVER_MONTH_BYTES_DOWNLOADED].as<size_t>();
|
||||||
|
server_used_quota += key->size;
|
||||||
|
for(const auto& trans : serverInstance->getFileServer()->pending_file_transfers())
|
||||||
|
server_used_quota += trans->size;
|
||||||
|
for(const auto& trans : serverInstance->getFileServer()->running_file_transfers())
|
||||||
|
server_used_quota += trans->remaining_bytes();
|
||||||
|
if(server_quota >= 0 && server_quota * 1024 * 1024 < (int64_t) server_used_quota) return command_result{error::file_transfer_server_quota_exceeded};
|
||||||
|
|
||||||
|
|
||||||
|
auto client_quota = this->calculate_permission(permission::i_ft_quota_mb_download_per_client, 0);
|
||||||
|
auto client_used_quota = this->properties()[property::CLIENT_MONTH_BYTES_DOWNLOADED].as<size_t>();
|
||||||
|
client_used_quota += key->size;
|
||||||
|
for(const auto& trans : serverInstance->getFileServer()->pending_file_transfers(_this.lock()))
|
||||||
|
client_used_quota += trans->size;
|
||||||
|
for(const auto& trans : serverInstance->getFileServer()->running_file_transfers(_this.lock()))
|
||||||
|
client_used_quota += trans->remaining_bytes();
|
||||||
|
|
||||||
|
if(client_quota.has_value && !client_quota.has_infinite_power() && (client_quota.value < 0 || client_quota.value * 1024 * 1024 < (int64_t) client_used_quota))
|
||||||
|
return command_result{error::file_transfer_client_quota_exceeded};
|
||||||
|
}
|
||||||
|
|
||||||
|
Command result(this->getExternalType() == CLIENT_TEAMSPEAK ? "notifystartdownload" : "");
|
||||||
|
result["clientftfid"] = cmd["clientftfid"].as<uint64_t>();
|
||||||
|
result["proto"] = 1;
|
||||||
|
result["serverftfid"] = key->key_id;
|
||||||
|
result["ftkey"] = key->key;
|
||||||
|
|
||||||
|
auto bindings = serverInstance->getFileServer()->list_bindings();
|
||||||
|
if(!bindings.empty()) {
|
||||||
|
result["port"] = net::port(bindings[0]->address);
|
||||||
|
string ip = "";
|
||||||
|
for(auto& entry : bindings) {
|
||||||
|
if(net::is_anybind(entry->address)) {
|
||||||
|
ip = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ip += net::to_string(entry->address, false) + ",";
|
||||||
|
}
|
||||||
|
if(!ip.empty())
|
||||||
|
result["ip"] = ip;
|
||||||
|
} else {
|
||||||
|
return command_result{error::server_is_not_running, "file server is not bound to any address"};
|
||||||
|
}
|
||||||
|
|
||||||
|
result["size"] = key->size;
|
||||||
|
this->sendCommand(result);
|
||||||
|
|
||||||
|
return command_result{error::ok};
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Usage: ftgetfileinfo cid={channelID} cpw={channelPassword} name={filePath}...
|
||||||
|
|
||||||
|
Permissions:
|
||||||
|
i_ft_file_browse_power
|
||||||
|
i_ft_needed_file_browse_power
|
||||||
|
|
||||||
|
Description:
|
||||||
|
Displays detailed information about one or more specified files stored in a
|
||||||
|
channels file repository.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
ftgetfileinfo cid=2 cpw= path=\/Pic1.PNG|cid=2 cpw= path=\/Pic2.PNG
|
||||||
|
cid=2 path=\/ name=Stuff size=0 datetime=1259415210 type=0|name=Pic1.PNG size=563783 datetime=1259425462 type=1|name=Pic2.PNG ...
|
||||||
|
error id=0 msg=ok
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
command_result ConnectedClient::handleCommandFTGetFileInfo(ts::Command &cmd) {
|
||||||
|
CMD_REQ_SERVER;
|
||||||
|
CMD_REQ_FSERVER;
|
||||||
|
CMD_RESET_IDLE;
|
||||||
|
|
||||||
|
Command result(this->getExternalType() == CLIENT_TEAMSPEAK ? "notifyfileinfo" : "");
|
||||||
|
|
||||||
|
int result_index = 0;
|
||||||
|
for(int index = 0; index < cmd.bulkCount(); index++) {
|
||||||
|
auto& request = cmd[index];
|
||||||
|
std::shared_ptr<file::FileEntry> file;
|
||||||
|
if (request.has("cid") && request["cid"].as<ChannelId>() != 0) { //Channel
|
||||||
|
auto channel = this->server->channelTree->findChannel(request["cid"].as<ChannelId>());
|
||||||
|
if (!channel) return command_result{error::channel_invalid_id, "Cant resolve channel"};
|
||||||
|
if (!channel->passwordMatch(cmd["cpw"]) && !permission::v2::permission_granted(1, this->calculate_permission(permission::b_ft_ignore_password, channel->channelId())))
|
||||||
|
return cmd["cpw"].string().empty() ? command_result{permission::b_ft_ignore_password} : command_result{error::channel_invalid_password};
|
||||||
|
|
||||||
|
ACTION_REQUIRES_CHANNEL_PERMISSION(channel, permission::i_ft_needed_file_browse_power, permission::i_ft_file_browse_power, true);
|
||||||
|
file = serverInstance->getFileServer()->findFile(request["name"],serverInstance->getFileServer()->resolveDirectory(this->server, channel, request["path"]));
|
||||||
|
} else {
|
||||||
|
std::shared_ptr<file::Directory> directory;
|
||||||
|
if (!request.has("path") || request["path"].as<string>() == "/") {
|
||||||
|
directory = serverInstance->getFileServer()->avatarDirectory(this->server);
|
||||||
|
} else if (request["path"].as<string>() == "/icons" || request["path"].as<string>() == "/icons/") {
|
||||||
|
directory = serverInstance->getFileServer()->iconDirectory(this->server);
|
||||||
|
} else {
|
||||||
|
cerr << "Unknown requested directory: '" << request["path"].as<std::string>() << "'" << endl;
|
||||||
|
return command_result{error::not_implemented};
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!directory) continue;
|
||||||
|
file = serverInstance->getFileServer()->findFile(cmd["name"].as<std::string>(), directory);
|
||||||
|
}
|
||||||
|
if(!file) continue;
|
||||||
|
|
||||||
|
result[result_index]["cid"] = request["cid"].as<ChannelId>();
|
||||||
|
result[result_index]["name"] = request["name"];
|
||||||
|
result[result_index]["path"] = request["path"];
|
||||||
|
result[result_index]["type"] = file->type;
|
||||||
|
result[result_index]["datetime"] = duration_cast<seconds>(file->lastChanged.time_since_epoch()).count();
|
||||||
|
if (file->type == file::FileType::FILE)
|
||||||
|
result[result_index]["size"] = static_pointer_cast<file::File>(file)->fileSize;
|
||||||
|
else
|
||||||
|
result[result_index]["size"] = 0;
|
||||||
|
result_index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result_index == 0)
|
||||||
|
return command_result{error::database_empty_result};
|
||||||
|
this->sendCommand(result);
|
||||||
|
|
||||||
|
return command_result{error::ok};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
193
server/src/client/command_handler/helpers.h
Normal file
193
server/src/client/command_handler/helpers.h
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/** Permission tests against required values **/
|
||||||
|
/* use this for any action which will do something with the server */
|
||||||
|
#define ACTION_REQUIRES_GLOBAL_PERMISSION_CACHED(required_permission_type, required_value, cache) \
|
||||||
|
do { \
|
||||||
|
if(!permission::v2::permission_granted(required_value, this->calculate_permission(required_permission_type, 0, false, cache))) \
|
||||||
|
return command_result{required_permission_type}; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define ACTION_REQUIRES_GLOBAL_PERMISSION(required_permission_type, required_value) \
|
||||||
|
ACTION_REQUIRES_GLOBAL_PERMISSION_CACHED(required_permission_type, required_value, nullptr)
|
||||||
|
|
||||||
|
//TODO: Fixme: Really check for instance permissions!
|
||||||
|
#define ACTION_REQUIRES_INSTANCE_PERMISSION(required_permission_type, required_value) \
|
||||||
|
ACTION_REQUIRES_GLOBAL_PERMISSION_CACHED(required_permission_type, required_value, nullptr)
|
||||||
|
|
||||||
|
/* use this for anything which will do something local in relation to the target channel */
|
||||||
|
#define ACTION_REQUIRES_PERMISSION(required_permission_type, required_value, channel_id) \
|
||||||
|
do { \
|
||||||
|
if(!permission::v2::permission_granted(required_value, this->calculate_permission(required_permission_type, channel_id))) \
|
||||||
|
return command_result{required_permission_type}; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
/** Permission tests against groups **/
|
||||||
|
/* use this when testing a permission against a group */
|
||||||
|
#define ACTION_REQUIRES_GROUP_PERMISSION(group, required_permission_type, own_permission_type, is_required) \
|
||||||
|
do { \
|
||||||
|
auto _permission_granted = this->calculate_permission(own_permission_type, 0); \
|
||||||
|
if(!(group)->permission_granted(required_permission_type, _permission_granted, is_required)) \
|
||||||
|
return command_result{own_permission_type}; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
/** Permission tests against channels **/
|
||||||
|
/* use this when testing a permission against a group */
|
||||||
|
#define ACTION_REQUIRES_CHANNEL_PERMISSION(channel, required_permission_type, own_permission_type, is_required) \
|
||||||
|
do { \
|
||||||
|
auto _permission_granted = this->calculate_permission(own_permission_type, channel ? channel->channelId() : 0); \
|
||||||
|
if(!(channel)->permission_granted(required_permission_type, _permission_granted, is_required)) \
|
||||||
|
return command_result{own_permission_type}; \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
|
||||||
|
/* Helper methods for channel resolve */
|
||||||
|
#define RESOLVE_CHANNEL_R(command, force) \
|
||||||
|
auto channel_tree = this->server ? this->server->channelTree : serverInstance->getChannelTree().get();\
|
||||||
|
shared_lock channel_tree_read_lock(this->server ? this->server->channel_tree_lock : serverInstance->getChannelTreeLock());\
|
||||||
|
auto channel_id = command.as<ChannelId>(); \
|
||||||
|
auto l_channel = channel_id ? channel_tree->findLinkedChannel(command.as<ChannelId>()) : nullptr; \
|
||||||
|
if (!l_channel && (channel_id != 0 || force)) return command_result{error::channel_invalid_id, "Cant resolve channel"}; \
|
||||||
|
|
||||||
|
#define RESOLVE_CHANNEL_W(command, force) \
|
||||||
|
auto channel_tree = this->server ? this->server->channelTree : serverInstance->getChannelTree().get();\
|
||||||
|
unique_lock channel_tree_write_lock(this->server ? this->server->channel_tree_lock : serverInstance->getChannelTreeLock());\
|
||||||
|
auto channel_id = command.as<ChannelId>(); \
|
||||||
|
auto l_channel = channel_id ? channel_tree->findLinkedChannel(command.as<ChannelId>()) : nullptr; \
|
||||||
|
if (!l_channel && (channel_id != 0 || force)) return command_result{error::channel_invalid_id, "Cant resolve channel"}; \
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//TODO: Map permsid!
|
||||||
|
#define PARSE_PERMISSION(cmd) \
|
||||||
|
permission::PermissionType permType = permission::PermissionType::unknown; \
|
||||||
|
bool grant = false; \
|
||||||
|
if (cmd[index].has("permid")) { \
|
||||||
|
permType = cmd[index]["permid"].as<permission::PermissionType>(); \
|
||||||
|
if ((permType & PERM_ID_GRANT) != 0) { \
|
||||||
|
grant = true; \
|
||||||
|
permType &= ~PERM_ID_GRANT; \
|
||||||
|
} \
|
||||||
|
} else if (cmd[index].has("permsid")) { \
|
||||||
|
auto resv = permission::resolvePermissionData(cmd[index]["permsid"].as<string>()); \
|
||||||
|
permType = resv->type; \
|
||||||
|
if (resv->grantName() == cmd[index]["permsid"].as<string>()) grant = true; \
|
||||||
|
} \
|
||||||
|
if (permission::resolvePermissionData(permType)->type == permission::PermissionType::unknown) { \
|
||||||
|
if (conOnError) continue; \
|
||||||
|
return ts::command_result{error::parameter_invalid}; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
inline bool permission_require_granted_value(ts::permission::PermissionType type) {
|
||||||
|
using namespace ts;
|
||||||
|
switch (type) {
|
||||||
|
case permission::i_permission_modify_power:
|
||||||
|
|
||||||
|
case permission::i_channel_group_member_add_power:
|
||||||
|
case permission::i_channel_group_member_remove_power:
|
||||||
|
case permission::i_channel_group_modify_power:
|
||||||
|
|
||||||
|
case permission::i_channel_group_needed_member_add_power:
|
||||||
|
case permission::i_channel_group_needed_member_remove_power:
|
||||||
|
case permission::i_channel_group_needed_modify_power:
|
||||||
|
|
||||||
|
|
||||||
|
case permission::i_server_group_member_add_power:
|
||||||
|
case permission::i_server_group_member_remove_power:
|
||||||
|
case permission::i_server_group_modify_power:
|
||||||
|
|
||||||
|
case permission::i_server_group_needed_member_add_power:
|
||||||
|
case permission::i_server_group_needed_member_remove_power:
|
||||||
|
case permission::i_server_group_needed_modify_power:
|
||||||
|
|
||||||
|
case permission::i_displayed_group_member_add_power:
|
||||||
|
case permission::i_displayed_group_member_remove_power:
|
||||||
|
case permission::i_displayed_group_modify_power:
|
||||||
|
|
||||||
|
case permission::i_displayed_group_needed_member_add_power:
|
||||||
|
case permission::i_displayed_group_needed_member_remove_power:
|
||||||
|
case permission::i_displayed_group_needed_modify_power:
|
||||||
|
|
||||||
|
case permission::i_channel_permission_modify_power:
|
||||||
|
case permission::i_channel_needed_permission_modify_power:
|
||||||
|
case permission::i_client_permission_modify_power:
|
||||||
|
case permission::i_client_needed_permission_modify_power:
|
||||||
|
|
||||||
|
case permission::i_client_needed_kick_from_server_power:
|
||||||
|
case permission::i_client_needed_kick_from_channel_power:
|
||||||
|
case permission::i_client_kick_from_channel_power:
|
||||||
|
case permission::i_client_kick_from_server_power:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool permission_is_group_property(ts::permission::PermissionType type) {
|
||||||
|
using namespace ts;
|
||||||
|
switch (type) {
|
||||||
|
case permission::i_icon_id:
|
||||||
|
case permission::i_group_show_name_in_tree:
|
||||||
|
case permission::i_group_sort_id:
|
||||||
|
case permission::b_group_is_permanent:
|
||||||
|
case permission::i_displayed_group_needed_modify_power:
|
||||||
|
case permission::i_displayed_group_needed_member_add_power:
|
||||||
|
case permission::i_displayed_group_needed_member_remove_power:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool permission_is_client_property(ts::permission::PermissionType type) {
|
||||||
|
using namespace ts;
|
||||||
|
switch (type) {
|
||||||
|
case permission::i_icon_id:
|
||||||
|
case permission::i_client_talk_power:
|
||||||
|
case permission::i_client_max_idletime:
|
||||||
|
case permission::i_group_sort_id:
|
||||||
|
case permission::i_channel_view_power:
|
||||||
|
case permission::b_channel_ignore_view_power:
|
||||||
|
case permission::b_client_is_priority_speaker:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline ssize_t count_characters(const std::string& in) {
|
||||||
|
size_t index = 0;
|
||||||
|
size_t count = 0;
|
||||||
|
while(index < in.length()){
|
||||||
|
count++;
|
||||||
|
|
||||||
|
auto current = (uint8_t) in[index];
|
||||||
|
if(current >= 128) { //UTF8 check
|
||||||
|
if(current >= 192 && (current <= 193 || current >= 245)) {
|
||||||
|
return -1;
|
||||||
|
} else if(current >= 194 && current <= 223) {
|
||||||
|
if(in.length() - index <= 1) return -1;
|
||||||
|
else if((uint8_t) in[index + 1] >= 128 && (uint8_t) in[index + 1] <= 191) index += 1; //Valid
|
||||||
|
else return -1;
|
||||||
|
} else if(current >= 224 && current <= 239) {
|
||||||
|
if(in.length() - index <= 2) return -1;
|
||||||
|
else if((uint8_t) in[index + 1] >= 128 && (uint8_t) in[index + 1] <= 191 &&
|
||||||
|
(uint8_t) in[index + 2] >= 128 && (uint8_t) in[index + 2] <= 191) index += 2; //Valid
|
||||||
|
else return -1;
|
||||||
|
} else if(current >= 240 && current <= 244) {
|
||||||
|
if(in.length() - index <= 3) return -1;
|
||||||
|
else if((uint8_t) in[index + 1] >= 128 && (uint8_t) in[index + 1] <= 191 &&
|
||||||
|
(uint8_t) in[index + 2] >= 128 && (uint8_t) in[index + 2] <= 191 &&
|
||||||
|
(uint8_t) in[index + 3] >= 128 && (uint8_t) in[index + 3] <= 191) index += 3; //Valid
|
||||||
|
else return -1;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
2579
server/src/client/command_handler/misc.cpp
Normal file
2579
server/src/client/command_handler/misc.cpp
Normal file
File diff suppressed because it is too large
Load Diff
924
server/src/client/command_handler/music.cpp
Normal file
924
server/src/client/command_handler/music.cpp
Normal file
@ -0,0 +1,924 @@
|
|||||||
|
//
|
||||||
|
// Created by wolverindev on 26.01.20.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <spdlog/sinks/rotating_file_sink.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <bitset>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
#include "../../build.h"
|
||||||
|
#include "../ConnectedClient.h"
|
||||||
|
#include "../InternalClient.h"
|
||||||
|
#include "../../server/file/FileServer.h"
|
||||||
|
#include "../../server/VoiceServer.h"
|
||||||
|
#include "../voice/VoiceClient.h"
|
||||||
|
#include "PermissionManager.h"
|
||||||
|
#include "../../InstanceHandler.h"
|
||||||
|
#include "../../server/QueryServer.h"
|
||||||
|
#include "../file/FileClient.h"
|
||||||
|
#include "../music/MusicClient.h"
|
||||||
|
#include "../query/QueryClient.h"
|
||||||
|
#include "../../weblist/WebListManager.h"
|
||||||
|
#include "../../manager/ConversationManager.h"
|
||||||
|
#include "../../manager/PermissionNameMapper.h"
|
||||||
|
#include <experimental/filesystem>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <StringVariable.h>
|
||||||
|
|
||||||
|
#include "helpers.h"
|
||||||
|
|
||||||
|
#include <Properties.h>
|
||||||
|
#include <log/LogUtils.h>
|
||||||
|
#include <misc/sassert.h>
|
||||||
|
#include <misc/base64.h>
|
||||||
|
#include <misc/hex.h>
|
||||||
|
#include <misc/digest.h>
|
||||||
|
#include <misc/rnd.h>
|
||||||
|
#include <misc/timer.h>
|
||||||
|
#include <misc/strobf.h>
|
||||||
|
#include <misc/scope_guard.h>
|
||||||
|
#include <bbcode/bbcodes.h>
|
||||||
|
|
||||||
|
namespace fs = std::experimental::filesystem;
|
||||||
|
using namespace std::chrono;
|
||||||
|
using namespace std;
|
||||||
|
using namespace ts;
|
||||||
|
using namespace ts::server;
|
||||||
|
using namespace ts::token;
|
||||||
|
|
||||||
|
command_result ConnectedClient::handleCommandMusicBotCreate(Command& cmd) {
|
||||||
|
if(!config::music::enabled) return command_result{error::music_disabled};
|
||||||
|
|
||||||
|
CMD_REQ_SERVER;
|
||||||
|
CMD_RESET_IDLE;
|
||||||
|
CMD_CHK_AND_INC_FLOOD_POINTS(25);
|
||||||
|
|
||||||
|
if(this->server->musicManager->max_bots() != -1 && this->server->musicManager->max_bots() <= this->server->musicManager->current_bot_count()){
|
||||||
|
if(config::license->isPremium())
|
||||||
|
return command_result{error::music_limit_reached};
|
||||||
|
else
|
||||||
|
return command_result{error::music_limit_reached, strobf("You reached the server music bot limit. You could increase this limit by extend your server with a premium license.").string()};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
auto permissions_list = this->calculate_permissions({
|
||||||
|
permission::i_client_music_limit,
|
||||||
|
permission::b_client_music_create_permanent,
|
||||||
|
permission::b_client_music_create_semi_permanent,
|
||||||
|
permission::b_client_music_create_temporary,
|
||||||
|
permission::i_channel_join_power,
|
||||||
|
permission::i_client_music_delete_power,
|
||||||
|
permission::i_client_music_create_modify_max_volume
|
||||||
|
}, this->getChannelId());
|
||||||
|
|
||||||
|
auto permissions = map<permission::PermissionType, permission::v2::PermissionFlaggedValue>(permissions_list.begin(), permissions_list.end());
|
||||||
|
|
||||||
|
auto max_bots = permissions[permission::i_client_music_limit];
|
||||||
|
if(max_bots.has_value) {
|
||||||
|
auto ownBots = this->server->musicManager->listBots(this->getClientDatabaseId());
|
||||||
|
if(!permission::v2::permission_granted(ownBots.size() + 1, max_bots))
|
||||||
|
return command_result{error::music_client_limit_reached};
|
||||||
|
}
|
||||||
|
|
||||||
|
MusicClient::Type::value create_type;
|
||||||
|
if(cmd[0].has("type")) {
|
||||||
|
create_type = cmd["type"].as<MusicClient::Type::value>();
|
||||||
|
switch(create_type) {
|
||||||
|
case MusicClient::Type::PERMANENT:
|
||||||
|
if(!permission::v2::permission_granted(1, permissions[permission::b_client_music_create_permanent]))
|
||||||
|
return command_result{permission::b_client_music_create_permanent};
|
||||||
|
break;
|
||||||
|
case MusicClient::Type::SEMI_PERMANENT:
|
||||||
|
if(!permission::v2::permission_granted(1, permissions[permission::b_client_music_create_semi_permanent]))
|
||||||
|
return command_result{permission::b_client_music_create_semi_permanent};
|
||||||
|
break;
|
||||||
|
case MusicClient::Type::TEMPORARY:
|
||||||
|
if(!permission::v2::permission_granted(1, permissions[permission::b_client_music_create_temporary]))
|
||||||
|
return command_result{permission::b_client_music_create_temporary};
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return command_result{error::vs_critical};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(permission::v2::permission_granted(1, permissions[permission::b_client_music_create_permanent]))
|
||||||
|
create_type = MusicClient::Type::PERMANENT;
|
||||||
|
else if(permission::v2::permission_granted(1, permissions[permission::b_client_music_create_semi_permanent]))
|
||||||
|
create_type = MusicClient::Type::SEMI_PERMANENT;
|
||||||
|
else if(permission::v2::permission_granted(1, permissions[permission::b_client_music_create_temporary]))
|
||||||
|
create_type = MusicClient::Type::TEMPORARY;
|
||||||
|
else
|
||||||
|
return command_result{permission::b_client_music_create_temporary};
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_lock server_channel_lock(this->server->channel_tree_lock);
|
||||||
|
auto channel = cmd[0].has("cid") ? this->server->channelTree->findChannel(cmd["cid"]) : this->currentChannel;
|
||||||
|
if(!channel) {
|
||||||
|
if(cmd[0].has("cid")) return command_result{error::channel_invalid_id};
|
||||||
|
} else {
|
||||||
|
if(!this->calculate_and_get_join_state(channel))
|
||||||
|
channel = nullptr;
|
||||||
|
}
|
||||||
|
if(!channel)
|
||||||
|
channel = this->server->channelTree->getDefaultChannel();
|
||||||
|
|
||||||
|
auto bot = this->server->musicManager->createBot(this->getClientDatabaseId());
|
||||||
|
if(!bot) return command_result{error::vs_critical};
|
||||||
|
bot->set_bot_type(create_type);
|
||||||
|
if(permissions[permission::i_client_music_create_modify_max_volume].has_value) {
|
||||||
|
auto max_volume = min(100, max(0, permissions[permission::i_client_music_create_modify_max_volume].value));
|
||||||
|
if(max_volume >= 0)
|
||||||
|
bot->volume_modifier(max_volume / 100.f);
|
||||||
|
}
|
||||||
|
this->selectedBot = bot;
|
||||||
|
|
||||||
|
{
|
||||||
|
server_channel_lock.unlock();
|
||||||
|
unique_lock server_channel_w_lock(this->server->channel_tree_lock);
|
||||||
|
this->server->client_move(
|
||||||
|
bot,
|
||||||
|
channel,
|
||||||
|
nullptr,
|
||||||
|
"music bot created",
|
||||||
|
ViewReasonId::VREASON_USER_ACTION,
|
||||||
|
false,
|
||||||
|
server_channel_w_lock
|
||||||
|
);
|
||||||
|
}
|
||||||
|
bot->properties()[property::CLIENT_LAST_CHANNEL] = channel ? channel->channelId() : 0;
|
||||||
|
bot->properties()[property::CLIENT_COUNTRY] = config::geo::countryFlag;
|
||||||
|
|
||||||
|
if(permissions[permission::i_client_music_delete_power].has_value && permissions[permission::i_client_music_delete_power].value >= 0) {
|
||||||
|
bot->clientPermissions->set_permission(permission::i_client_music_needed_delete_power, {permissions[permission::i_client_music_delete_power].value,0}, permission::v2::set_value, permission::v2::do_nothing);
|
||||||
|
}
|
||||||
|
|
||||||
|
Command notify(this->getExternalType() == ClientType::CLIENT_TEAMSPEAK ? "notifymusiccreated" : "");
|
||||||
|
notify["bot_id"] = bot->getClientDatabaseId();
|
||||||
|
this->sendCommand(notify);
|
||||||
|
|
||||||
|
return command_result{error::ok};
|
||||||
|
}
|
||||||
|
|
||||||
|
command_result ConnectedClient::handleCommandMusicBotDelete(Command& cmd) {
|
||||||
|
if(!config::music::enabled) return command_result{error::music_disabled};
|
||||||
|
|
||||||
|
CMD_REQ_SERVER;
|
||||||
|
CMD_RESET_IDLE;
|
||||||
|
CMD_CHK_AND_INC_FLOOD_POINTS(25);
|
||||||
|
|
||||||
|
auto bot = this->server->musicManager->findBotById(cmd["bot_id"]);
|
||||||
|
if(!bot) return command_result{error::music_invalid_id};
|
||||||
|
|
||||||
|
if(bot->getOwner() != this->getClientDatabaseId()) {
|
||||||
|
ACTION_REQUIRES_PERMISSION(permission::i_client_music_delete_power, bot->calculate_permission(permission::i_client_music_needed_delete_power, bot->getChannelId()), this->getChannelId());
|
||||||
|
}
|
||||||
|
|
||||||
|
this->server->musicManager->deleteBot(bot);
|
||||||
|
return command_result{error::ok};
|
||||||
|
}
|
||||||
|
|
||||||
|
command_result ConnectedClient::handleCommandMusicBotSetSubscription(ts::Command &cmd) {
|
||||||
|
if(!config::music::enabled) return command_result{error::music_disabled};
|
||||||
|
|
||||||
|
auto bot = this->server->musicManager->findBotById(cmd["bot_id"]);
|
||||||
|
if(!bot && cmd["bot_id"].as<ClientDbId>() != 0) return command_result{error::music_invalid_id};
|
||||||
|
|
||||||
|
{
|
||||||
|
auto old_bot = this->subscribed_bot.lock();
|
||||||
|
if(old_bot)
|
||||||
|
old_bot->remove_subscriber(_this.lock());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(bot) {
|
||||||
|
bot->add_subscriber(_this.lock());
|
||||||
|
this->subscribed_bot = bot;
|
||||||
|
}
|
||||||
|
|
||||||
|
return command_result{error::ok};
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply_song(Command& command, const std::shared_ptr<ts::music::SongInfo>& element, int index = 0) {
|
||||||
|
if(!element) return;
|
||||||
|
|
||||||
|
command[index]["song_id"] = element ? element->getSongId() : 0;
|
||||||
|
command[index]["song_url"] = element ? element->getUrl() : "";
|
||||||
|
command[index]["song_invoker"] = element ? element->getInvoker() : 0;
|
||||||
|
command[index]["song_loaded"] = false;
|
||||||
|
|
||||||
|
auto entry = dynamic_pointer_cast<ts::music::PlayableSong>(element);
|
||||||
|
if(entry) {
|
||||||
|
auto data = entry->song_loaded_data();
|
||||||
|
command[index]["song_loaded"] = entry->song_loaded() && data;
|
||||||
|
|
||||||
|
if(entry->song_loaded() && data) {
|
||||||
|
command[index]["song_title"] = data->title;
|
||||||
|
command[index]["song_description"] = data->description;
|
||||||
|
command[index]["song_thumbnail"] = data->thumbnail;
|
||||||
|
command[index]["song_length"] = data->length.count();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
command_result ConnectedClient::handleCommandMusicBotPlayerInfo(Command& cmd) {
|
||||||
|
if(!config::music::enabled) return command_result{error::music_disabled};
|
||||||
|
|
||||||
|
CMD_REQ_SERVER;
|
||||||
|
CMD_RESET_IDLE;
|
||||||
|
CMD_CHK_AND_INC_FLOOD_POINTS(5);
|
||||||
|
|
||||||
|
auto bot = this->server->musicManager->findBotById(cmd["bot_id"]);
|
||||||
|
if(!bot) return command_result{error::music_invalid_id};
|
||||||
|
|
||||||
|
Command result(this->getExternalType() == CLIENT_TEAMSPEAK ? "notifymusicplayerinfo" : "");
|
||||||
|
result["bot_id"] = bot->getClientDatabaseId();
|
||||||
|
|
||||||
|
result["player_state"] =(int) bot->player_state();
|
||||||
|
if(bot->current_player()) {
|
||||||
|
result["player_buffered_index"] = bot->current_player()->bufferedUntil().count();
|
||||||
|
result["player_replay_index"] = bot->current_player()->currentIndex().count();
|
||||||
|
result["player_max_index"] = bot->current_player()->length().count();
|
||||||
|
result["player_seekable"] = bot->current_player()->seek_supported();
|
||||||
|
|
||||||
|
result["player_title"] = bot->current_player()->songTitle();
|
||||||
|
result["player_description"] = bot->current_player()->songDescription();
|
||||||
|
} else {
|
||||||
|
result["player_buffered_index"] = 0;
|
||||||
|
result["player_replay_index"] = 0;
|
||||||
|
result["player_max_index"] = 0;
|
||||||
|
result["player_seekable"] = 0;
|
||||||
|
result["player_title"] = "";
|
||||||
|
result["player_description"] = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
apply_song(result, bot->current_song());
|
||||||
|
this->sendCommand(result);
|
||||||
|
|
||||||
|
return command_result{error::ok};
|
||||||
|
}
|
||||||
|
|
||||||
|
command_result ConnectedClient::handleCommandMusicBotPlayerAction(Command& cmd) {
|
||||||
|
if(!config::music::enabled) return command_result{error::music_disabled};
|
||||||
|
|
||||||
|
CMD_REQ_SERVER;
|
||||||
|
CMD_RESET_IDLE;
|
||||||
|
CMD_CHK_AND_INC_FLOOD_POINTS(25);
|
||||||
|
|
||||||
|
auto bot = this->server->musicManager->findBotById(cmd["bot_id"]);
|
||||||
|
if(!bot) return command_result{error::music_invalid_id};
|
||||||
|
ACTION_REQUIRES_PERMISSION(permission::i_client_music_play_power, bot->calculate_permission(permission::i_client_music_needed_play_power, bot->getChannelId()), this->getChannelId());
|
||||||
|
|
||||||
|
if(cmd["action"] == 0) {
|
||||||
|
bot->stopMusic();
|
||||||
|
} else if(cmd["action"] == 1) {
|
||||||
|
bot->playMusic();
|
||||||
|
} else if(cmd["action"] == 2) {
|
||||||
|
bot->player_pause();
|
||||||
|
} else if(cmd["action"] == 3) {
|
||||||
|
bot->forwardSong();
|
||||||
|
} else if(cmd["action"] == 4) {
|
||||||
|
bot->rewindSong();
|
||||||
|
} else if(cmd["action"] == 5) {
|
||||||
|
if(!bot->current_player()) return command_result{error::music_no_player};
|
||||||
|
bot->current_player()->forward(::music::PlayerUnits(cmd["units"].as<int64_t>()));
|
||||||
|
} else if(cmd["action"] == 6) {
|
||||||
|
if(!bot->current_player()) return command_result{error::music_no_player};
|
||||||
|
bot->current_player()->rewind(::music::PlayerUnits(cmd["units"].as<int64_t>()));
|
||||||
|
} else return command_result{error::music_invalid_action};
|
||||||
|
|
||||||
|
return command_result{error::ok};
|
||||||
|
}
|
||||||
|
|
||||||
|
command_result ConnectedClient::handleCommandPlaylistList(ts::Command &cmd) {
|
||||||
|
CMD_REQ_SERVER;
|
||||||
|
CMD_RESET_IDLE;
|
||||||
|
CMD_CHK_AND_INC_FLOOD_POINTS(25);
|
||||||
|
|
||||||
|
auto self_dbid = this->getClientDatabaseId();
|
||||||
|
auto playlist_view_power = this->calculate_permission(permission::i_playlist_view_power, 0);
|
||||||
|
auto playlists = this->server->musicManager->playlists();
|
||||||
|
|
||||||
|
playlists.erase(find_if(playlists.begin(), playlists.end(), [&](const shared_ptr<music::PlayablePlaylist>& playlist) {
|
||||||
|
if(playlist->properties()[property::PLAYLIST_OWNER_DBID] == self_dbid)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto needed_view_power = playlist->permissions()->getPermissionValue(permission::i_playlist_needed_view_power);
|
||||||
|
return !permission::v2::permission_granted(needed_view_power, playlist_view_power, false);;
|
||||||
|
}), playlists.end());
|
||||||
|
|
||||||
|
if(playlists.empty())
|
||||||
|
return command_result{error::database_empty_result};
|
||||||
|
|
||||||
|
Command notify(this->notify_response_command("notifyplaylistlist"));
|
||||||
|
|
||||||
|
size_t index = 0;
|
||||||
|
for(const auto& entry : playlists) {
|
||||||
|
notify[index]["playlist_id"] = entry->playlist_id();
|
||||||
|
auto bot = entry->current_bot();
|
||||||
|
notify[index]["playlist_bot_id"] = bot ? bot->getClientDatabaseId() : 0;
|
||||||
|
notify[index]["playlist_title"] = entry->properties()[property::PLAYLIST_TITLE].value();
|
||||||
|
notify[index]["playlist_type"] = entry->properties()[property::PLAYLIST_TYPE].value();
|
||||||
|
notify[index]["playlist_owner_dbid"] = entry->properties()[property::PLAYLIST_OWNER_DBID].value();
|
||||||
|
notify[index]["playlist_owner_name"] = entry->properties()[property::PLAYLIST_OWNER_NAME].value();
|
||||||
|
notify[index]["needed_power_modify"] = entry->permissions()->getPermissionValue(permission::i_playlist_needed_modify_power);
|
||||||
|
notify[index]["needed_power_permission_modify"] = entry->permissions()->getPermissionValue(permission::i_playlist_needed_permission_modify_power);
|
||||||
|
notify[index]["needed_power_delete"] = entry->permissions()->getPermissionValue(permission::i_playlist_needed_delete_power);
|
||||||
|
notify[index]["needed_power_song_add"] = entry->permissions()->getPermissionValue(permission::i_playlist_song_needed_add_power);
|
||||||
|
notify[index]["needed_power_song_move"] = entry->permissions()->getPermissionValue(permission::i_playlist_song_needed_move_power);
|
||||||
|
notify[index]["needed_power_song_remove"] = entry->permissions()->getPermissionValue(permission::i_playlist_song_needed_remove_power);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->sendCommand(notify);
|
||||||
|
return command_result{error::ok};
|
||||||
|
}
|
||||||
|
|
||||||
|
command_result ConnectedClient::handleCommandPlaylistCreate(ts::Command &cmd) {
|
||||||
|
CMD_REF_SERVER(ref_server);
|
||||||
|
CMD_RESET_IDLE;
|
||||||
|
CMD_CHK_AND_INC_FLOOD_POINTS(25);
|
||||||
|
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_playlist_create, 1);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto max_playlists = this->calculate_permission(permission::i_max_playlists, 0);
|
||||||
|
if(max_playlists.has_value) {
|
||||||
|
auto playlists = ref_server->musicManager->find_playlists_by_client(this->getClientDatabaseId());
|
||||||
|
if(!permission::v2::permission_granted(playlists.size(), max_playlists))
|
||||||
|
return command_result{permission::i_max_playlists};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto playlist = ref_server->musicManager->create_playlist(this->getClientDatabaseId(), this->getDisplayName());
|
||||||
|
if(!playlist) return command_result{error::vs_critical};
|
||||||
|
|
||||||
|
playlist->properties()[property::PLAYLIST_TYPE] = music::Playlist::Type::GENERAL;
|
||||||
|
|
||||||
|
{
|
||||||
|
auto max_songs = this->calculate_permission(permission::i_max_playlist_size, 0);
|
||||||
|
if(max_songs.has_value && max_songs.value >= 0)
|
||||||
|
playlist->properties()[property::PLAYLIST_MAX_SONGS] = max_songs.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto power = this->calculate_permission(permission::i_playlist_song_remove_power, 0);
|
||||||
|
if(power.has_value && power.value >= 0)
|
||||||
|
playlist->permissions()->setPermission(permission::i_playlist_song_needed_remove_power, power.value, nullptr);
|
||||||
|
|
||||||
|
power = this->calculate_permission(permission::i_playlist_delete_power, 0);
|
||||||
|
if(power.has_value && power.value >= 0)
|
||||||
|
playlist->permissions()->setPermission(permission::i_playlist_needed_delete_power, power.value, nullptr);
|
||||||
|
|
||||||
|
power = this->calculate_permission(permission::i_playlist_modify_power, 0);
|
||||||
|
if(power.has_value && power.value >= 0)
|
||||||
|
playlist->permissions()->setPermission(permission::i_playlist_needed_modify_power, power.value, nullptr);
|
||||||
|
|
||||||
|
power = this->calculate_permission(permission::i_playlist_permission_modify_power, 0);
|
||||||
|
if(power.has_value && power.value >= 0)
|
||||||
|
playlist->permissions()->setPermission(permission::i_playlist_needed_permission_modify_power, power.value, nullptr);
|
||||||
|
|
||||||
|
Command notify(this->notify_response_command("notifyplaylistcreated"));
|
||||||
|
notify["playlist_id"] = playlist->playlist_id();
|
||||||
|
this->sendCommand(notify);
|
||||||
|
|
||||||
|
return command_result{error::ok};
|
||||||
|
}
|
||||||
|
|
||||||
|
command_result ConnectedClient::handleCommandPlaylistDelete(ts::Command &cmd) {
|
||||||
|
CMD_REF_SERVER(ref_server);
|
||||||
|
CMD_RESET_IDLE;
|
||||||
|
CMD_CHK_AND_INC_FLOOD_POINTS(25);
|
||||||
|
|
||||||
|
auto playlist = ref_server->musicManager->find_playlist(cmd["playlist_id"]);
|
||||||
|
if(!playlist) return command_result{error::playlist_invalid_id};
|
||||||
|
|
||||||
|
if(playlist->properties()[property::PLAYLIST_OWNER_DBID] != this->getClientDatabaseId())
|
||||||
|
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::i_playlist_delete_power, playlist->permissions()->getPermissionValue(permission::i_playlist_needed_delete_power));
|
||||||
|
|
||||||
|
string error;
|
||||||
|
if(!ref_server->musicManager->delete_playlist(playlist->playlist_id(), error)) {
|
||||||
|
logError(this->getServerId(), "Failed to delete playlist with id {}. Error: {}", playlist->playlist_id(), error);
|
||||||
|
return command_result{error::vs_critical};
|
||||||
|
}
|
||||||
|
|
||||||
|
return command_result{error::ok};
|
||||||
|
}
|
||||||
|
|
||||||
|
command_result ConnectedClient::handleCommandPlaylistInfo(ts::Command &cmd) {
|
||||||
|
CMD_REF_SERVER(ref_server);
|
||||||
|
CMD_RESET_IDLE;
|
||||||
|
CMD_CHK_AND_INC_FLOOD_POINTS(25);
|
||||||
|
|
||||||
|
auto playlist = ref_server->musicManager->find_playlist(cmd["playlist_id"]);
|
||||||
|
if(!playlist) return command_result{error::playlist_invalid_id};
|
||||||
|
|
||||||
|
if(playlist->properties()[property::PLAYLIST_OWNER_DBID] != this->getClientDatabaseId())
|
||||||
|
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::i_playlist_view_power, playlist->permissions()->getPermissionValue(permission::i_playlist_needed_view_power));
|
||||||
|
|
||||||
|
|
||||||
|
Command notify(this->notify_response_command("notifyplaylistinfo"));
|
||||||
|
for(const auto& property : playlist->properties().list_properties(property::FLAG_PLAYLIST_VARIABLE)) {
|
||||||
|
notify[property.type().name] = property.value();
|
||||||
|
}
|
||||||
|
this->sendCommand(notify);
|
||||||
|
|
||||||
|
return command_result{error::ok};
|
||||||
|
}
|
||||||
|
|
||||||
|
command_result ConnectedClient::handleCommandPlaylistEdit(ts::Command &cmd) {
|
||||||
|
CMD_REF_SERVER(ref_server);
|
||||||
|
CMD_RESET_IDLE;
|
||||||
|
CMD_CHK_AND_INC_FLOOD_POINTS(25);
|
||||||
|
|
||||||
|
auto playlist = ref_server->musicManager->find_playlist(cmd["playlist_id"]);
|
||||||
|
if(!playlist) return command_result{error::playlist_invalid_id};
|
||||||
|
|
||||||
|
if(playlist->properties()[property::PLAYLIST_OWNER_DBID] != this->getClientDatabaseId())
|
||||||
|
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::i_playlist_modify_power, playlist->permissions()->getPermissionValue(permission::i_playlist_needed_modify_power));
|
||||||
|
|
||||||
|
deque<pair<shared_ptr<property::PropertyDescription>, string>> properties;
|
||||||
|
|
||||||
|
for(const auto& key : cmd[0].keys()) {
|
||||||
|
if(key == "playlist_id") continue;
|
||||||
|
if(key == "return_code") continue;
|
||||||
|
|
||||||
|
auto property = property::info<property::PlaylistProperties>(key);
|
||||||
|
if(*property == property::PLAYLIST_UNDEFINED) {
|
||||||
|
logError(this->getServerId(), R"([{}] Tried to edit a not existing playlist property "{}" to "{}")", CLIENT_STR_LOG_PREFIX, key, cmd[key].string());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((property->flags & property::FLAG_USER_EDITABLE) == 0) {
|
||||||
|
logError(this->getServerId(), "[{}] Tried to change a playlist property which is not changeable. (Key: {}, Value: \"{}\")", CLIENT_STR_LOG_PREFIX, key, cmd[key].string());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!property->validate_input(cmd[key].as<string>())) {
|
||||||
|
logError(this->getServerId(), "[{}] Tried to change a playlist property to an invalid value. (Key: {}, Value: \"{}\")", CLIENT_STR_LOG_PREFIX, key, cmd[key].string());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(*property == property::PLAYLIST_CURRENT_SONG_ID) {
|
||||||
|
auto song_id = cmd[key].as<SongId>();
|
||||||
|
auto song = song_id > 0 ? playlist->find_song(song_id) : nullptr;
|
||||||
|
if(song_id != 0 && !song)
|
||||||
|
return command_result{error::playlist_invalid_song_id};
|
||||||
|
} else if(*property == property::PLAYLIST_MAX_SONGS) {
|
||||||
|
auto value = cmd[key].as<int32_t>();
|
||||||
|
auto max_value = this->calculate_permission(permission::i_max_playlist_size, this->getChannelId());
|
||||||
|
if(max_value.has_value && !permission::v2::permission_granted(value, max_value))
|
||||||
|
return command_result{permission::i_max_playlist_size};
|
||||||
|
}
|
||||||
|
|
||||||
|
properties.emplace_back(property, key);
|
||||||
|
}
|
||||||
|
for(const auto& property : properties) {
|
||||||
|
if(*property.first == property::PLAYLIST_CURRENT_SONG_ID) {
|
||||||
|
playlist->set_current_song(cmd[property.second]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
playlist->properties()[property.first] = cmd[property.second].string();
|
||||||
|
}
|
||||||
|
return command_result{error::ok};
|
||||||
|
}
|
||||||
|
|
||||||
|
command_result ConnectedClient::handleCommandPlaylistPermList(ts::Command &cmd) {
|
||||||
|
CMD_REF_SERVER(ref_server);
|
||||||
|
CMD_RESET_IDLE;
|
||||||
|
CMD_CHK_AND_INC_FLOOD_POINTS(25);
|
||||||
|
|
||||||
|
auto playlist = ref_server->musicManager->find_playlist(cmd["playlist_id"]);
|
||||||
|
if(!playlist) return command_result{error::playlist_invalid_id};
|
||||||
|
|
||||||
|
if(playlist->properties()[property::PLAYLIST_OWNER_DBID] != this->getClientDatabaseId())
|
||||||
|
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_playlist_permission_list, 1);
|
||||||
|
|
||||||
|
auto permissions = playlist->permissions()->listPermissions(PERM_FLAG_PUBLIC);
|
||||||
|
if(permissions.empty())
|
||||||
|
return command_result{error::vs_critical};
|
||||||
|
|
||||||
|
Command result(this->notify_response_command("notifyplaylistpermlist"));
|
||||||
|
int index = 0;
|
||||||
|
result["playlist_id"] = playlist->playlist_id();
|
||||||
|
for (const auto &elm : permissions) {
|
||||||
|
if(elm->hasValue()) {
|
||||||
|
result[index]["permid"] = elm->type->type;
|
||||||
|
|
||||||
|
result[index]["permvalue"] = elm->value;
|
||||||
|
result[index]["permnegated"] = elm->flag_negate;
|
||||||
|
result[index]["permskip"] = elm->flag_skip;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
if(elm->hasGrant()) {
|
||||||
|
result[index]["permid"] = (uint16_t) (elm->type->type | PERM_ID_GRANT);
|
||||||
|
result[index]["permvalue"] = elm->granted;
|
||||||
|
result[index]["permnegated"] = 0;
|
||||||
|
result[index]["permskip"] = 0;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this->sendCommand(result);
|
||||||
|
|
||||||
|
return command_result{error::ok};
|
||||||
|
}
|
||||||
|
|
||||||
|
command_result ConnectedClient::handleCommandPlaylistAddPerm(ts::Command &cmd) {
|
||||||
|
CMD_REF_SERVER(ref_server);
|
||||||
|
CMD_RESET_IDLE;
|
||||||
|
CMD_CHK_AND_INC_FLOOD_POINTS(5);
|
||||||
|
|
||||||
|
auto playlist = ref_server->musicManager->find_playlist(cmd["playlist_id"]);
|
||||||
|
if(!playlist) return command_result{error::playlist_invalid_id};
|
||||||
|
|
||||||
|
if(playlist->properties()[property::PLAYLIST_OWNER_DBID] != this->getClientDatabaseId())
|
||||||
|
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::i_playlist_permission_modify_power, playlist->permissions()->getPermissionValue(permission::i_playlist_needed_permission_modify_power));
|
||||||
|
|
||||||
|
auto max_value = this->calculate_permission(permission::i_permission_modify_power, 0, true);
|
||||||
|
if(!max_value.has_value) return command_result{permission::i_permission_modify_power};
|
||||||
|
|
||||||
|
auto ignore_granted_values = permission::v2::permission_granted(1, this->calculate_permission(permission::b_permission_modify_power_ignore, 0));
|
||||||
|
|
||||||
|
|
||||||
|
bool conOnError = cmd[0].has("continueonerror");
|
||||||
|
for (int index = 0; index < cmd.bulkCount(); index++) {
|
||||||
|
PARSE_PERMISSION(cmd);
|
||||||
|
|
||||||
|
auto val = cmd[index]["permvalue"].as<permission::PermissionValue>();
|
||||||
|
if(permission_require_granted_value(permType) && !permission::v2::permission_granted(val, max_value)) {
|
||||||
|
if(conOnError) continue;
|
||||||
|
return command_result{permission::i_permission_modify_power};
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!ignore_granted_values && !permission::v2::permission_granted(val, this->calculate_permission(permType, 0, true))) {
|
||||||
|
if(conOnError) continue;
|
||||||
|
return command_result{permission::i_permission_modify_power};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grant) {
|
||||||
|
playlist->permissions()->setPermissionGranted(permType, cmd[index]["permvalue"], nullptr);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
playlist->permissions()->setPermission(permType, cmd[index]["permvalue"], nullptr, cmd[index]["permskip"], cmd[index]["permnegated"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return command_result{error::ok};
|
||||||
|
}
|
||||||
|
|
||||||
|
command_result ConnectedClient::handleCommandPlaylistDelPerm(ts::Command &cmd) {
|
||||||
|
CMD_REF_SERVER(ref_server);
|
||||||
|
CMD_RESET_IDLE;
|
||||||
|
CMD_CHK_AND_INC_FLOOD_POINTS(5);
|
||||||
|
|
||||||
|
auto playlist = ref_server->musicManager->find_playlist(cmd["playlist_id"]);
|
||||||
|
if(!playlist) return command_result{error::playlist_invalid_id};
|
||||||
|
|
||||||
|
if(playlist->properties()[property::PLAYLIST_OWNER_DBID] != this->getClientDatabaseId())
|
||||||
|
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::i_playlist_permission_modify_power, playlist->permissions()->getPermissionValue(permission::i_playlist_needed_permission_modify_power));
|
||||||
|
|
||||||
|
auto ignore_granted_values = permission::v2::permission_granted(1, this->calculate_permission(permission::b_permission_modify_power_ignore, 0));
|
||||||
|
bool conOnError = cmd[0].has("continueonerror");
|
||||||
|
|
||||||
|
for (int index = 0; index < cmd.bulkCount(); index++) {
|
||||||
|
PARSE_PERMISSION(cmd);
|
||||||
|
|
||||||
|
if(!ignore_granted_values && !permission::v2::permission_granted(0, this->calculate_permission(permType, 0, true))) {
|
||||||
|
if(conOnError) continue;
|
||||||
|
return command_result{permission::i_permission_modify_power};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (grant) {
|
||||||
|
playlist->permissions()->setPermissionGranted(permType, permNotGranted, nullptr);
|
||||||
|
} else {
|
||||||
|
playlist->permissions()->deletePermission(permType, nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return command_result{error::ok};
|
||||||
|
}
|
||||||
|
|
||||||
|
command_result ConnectedClient::handleCommandPlaylistSongList(ts::Command &cmd) {
|
||||||
|
CMD_REF_SERVER(ref_server);
|
||||||
|
CMD_RESET_IDLE;
|
||||||
|
CMD_CHK_AND_INC_FLOOD_POINTS(25);
|
||||||
|
|
||||||
|
auto playlist = ref_server->musicManager->find_playlist(cmd["playlist_id"]);
|
||||||
|
if(!playlist) return command_result{error::playlist_invalid_id};
|
||||||
|
|
||||||
|
if(playlist->properties()[property::PLAYLIST_OWNER_DBID] != this->getClientDatabaseId())
|
||||||
|
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::i_playlist_view_power, playlist->permissions()->getPermissionValue(permission::i_playlist_needed_view_power));
|
||||||
|
|
||||||
|
auto songs = playlist->list_songs();
|
||||||
|
if(songs.empty())
|
||||||
|
return command_result{error::database_empty_result};
|
||||||
|
|
||||||
|
Command notify(this->notify_response_command("notifyplaylistsonglist"));
|
||||||
|
notify["playlist_id"] = playlist->playlist_id();
|
||||||
|
|
||||||
|
size_t index = 0;
|
||||||
|
for(const auto& song : songs) {
|
||||||
|
notify[index]["song_id"] = song->id;
|
||||||
|
notify[index]["song_invoker"] = song->invoker;
|
||||||
|
notify[index]["song_previous_song_id"] = song->previous_song_id;
|
||||||
|
notify[index]["song_url"] = song->url;
|
||||||
|
notify[index]["song_url_loader"] = song->url_loader;
|
||||||
|
notify[index]["song_loaded"] = song->loaded;
|
||||||
|
notify[index]["song_metadata"] = song->metadata;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
this->sendCommand(notify);
|
||||||
|
|
||||||
|
return command_result{error::ok};
|
||||||
|
}
|
||||||
|
|
||||||
|
command_result ConnectedClient::handleCommandPlaylistSongAdd(ts::Command &cmd) {
|
||||||
|
CMD_REF_SERVER(ref_server);
|
||||||
|
CMD_RESET_IDLE;
|
||||||
|
CMD_CHK_AND_INC_FLOOD_POINTS(25);
|
||||||
|
|
||||||
|
auto playlist = ref_server->musicManager->find_playlist(cmd["playlist_id"]);
|
||||||
|
if(!playlist) return command_result{error::playlist_invalid_id};
|
||||||
|
|
||||||
|
if(playlist->properties()[property::PLAYLIST_OWNER_DBID] != this->getClientDatabaseId())
|
||||||
|
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::i_playlist_song_add_power, playlist->permissions()->getPermissionValue(permission::i_playlist_song_needed_add_power));
|
||||||
|
|
||||||
|
if(!cmd[0].has("invoker"))
|
||||||
|
cmd["invoker"] = "";
|
||||||
|
if(!cmd[0].has("previous")) {
|
||||||
|
auto songs = playlist->list_songs();
|
||||||
|
if(songs.empty())
|
||||||
|
cmd["previous"] = "0";
|
||||||
|
else
|
||||||
|
cmd["previous"] = songs.back()->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
auto song = playlist->add_song(_this.lock(), cmd["url"], cmd["invoker"], cmd["previous"]);
|
||||||
|
if(!song) return command_result{error::vs_critical};
|
||||||
|
|
||||||
|
Command notify(this->notify_response_command("notifyplaylistsongadd"));
|
||||||
|
notify["song_id"] = song->id;
|
||||||
|
this->sendCommand(notify);
|
||||||
|
|
||||||
|
return command_result{error::ok};
|
||||||
|
}
|
||||||
|
|
||||||
|
command_result ConnectedClient::handleCommandPlaylistSongReorder(ts::Command &cmd) {
|
||||||
|
CMD_REF_SERVER(ref_server);
|
||||||
|
CMD_RESET_IDLE;
|
||||||
|
CMD_CHK_AND_INC_FLOOD_POINTS(25);
|
||||||
|
|
||||||
|
auto playlist = ref_server->musicManager->find_playlist(cmd["playlist_id"]);
|
||||||
|
if(!playlist) return command_result{error::playlist_invalid_id};
|
||||||
|
|
||||||
|
if(playlist->properties()[property::PLAYLIST_OWNER_DBID] != this->getClientDatabaseId())
|
||||||
|
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::i_playlist_song_move_power, playlist->permissions()->getPermissionValue(permission::i_playlist_song_needed_move_power));
|
||||||
|
|
||||||
|
SongId song_id = cmd["song_id"];
|
||||||
|
SongId previous_id = cmd["song_previous_song_id"];
|
||||||
|
|
||||||
|
auto song = playlist->find_song(song_id);
|
||||||
|
if(!song) return command_result{error::playlist_invalid_song_id};
|
||||||
|
|
||||||
|
if(!playlist->reorder_song(song_id, previous_id))
|
||||||
|
return command_result{error::vs_critical};
|
||||||
|
|
||||||
|
return command_result{error::ok};
|
||||||
|
}
|
||||||
|
|
||||||
|
command_result ConnectedClient::handleCommandPlaylistSongRemove(ts::Command &cmd) {
|
||||||
|
CMD_REF_SERVER(ref_server);
|
||||||
|
CMD_RESET_IDLE;
|
||||||
|
CMD_CHK_AND_INC_FLOOD_POINTS(25);
|
||||||
|
|
||||||
|
auto playlist = ref_server->musicManager->find_playlist(cmd["playlist_id"]);
|
||||||
|
if(!playlist) return command_result{error::playlist_invalid_id};
|
||||||
|
|
||||||
|
if(playlist->properties()[property::PLAYLIST_OWNER_DBID] != this->getClientDatabaseId())
|
||||||
|
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::i_playlist_song_remove_power, playlist->permissions()->getPermissionValue(permission::i_playlist_song_needed_remove_power));
|
||||||
|
|
||||||
|
SongId song_id = cmd["song_id"];
|
||||||
|
|
||||||
|
auto song = playlist->find_song(song_id);
|
||||||
|
if(!song) return command_result{error::playlist_invalid_song_id};
|
||||||
|
|
||||||
|
if(!playlist->delete_song(song_id))
|
||||||
|
return command_result{error::vs_critical};
|
||||||
|
|
||||||
|
return command_result{error::ok};
|
||||||
|
}
|
||||||
|
|
||||||
|
command_result ConnectedClient::handleCommandMusicBotQueueList(Command& cmd) {
|
||||||
|
return command_result{error::not_implemented}; //FIXME
|
||||||
|
|
||||||
|
/*
|
||||||
|
CMD_REQ_SERVER;
|
||||||
|
CMD_RESET_IDLE;
|
||||||
|
CMD_CHK_AND_INC_FLOOD_POINTS(25);
|
||||||
|
|
||||||
|
auto bot = this->server->musicManager->findBotById(cmd["bot_id"]);
|
||||||
|
if(!bot) return command_result{error::music_invalid_id};
|
||||||
|
PERM_CHECK_CHANNELR(permission::i_client_music_info, bot->permissionValue(permission::i_client_music_needed_info, bot->currentChannel), this->currentChannel, true);
|
||||||
|
|
||||||
|
|
||||||
|
bool bulked = cmd.hasParm("bulk") || cmd.hasParm("balk") || cmd.hasParm("pipe") || cmd.hasParm("bar") || cmd.hasParm("paypal");
|
||||||
|
int command_index = 0;
|
||||||
|
|
||||||
|
Command notify(this->getExternalType() == CLIENT_VOICE ? "notifymusicqueueentry" : "");
|
||||||
|
{
|
||||||
|
auto history = bot->queue()->history();
|
||||||
|
for(int index = history.size(); index > 0; index--) {
|
||||||
|
if(!bulked)
|
||||||
|
notify = Command(this->getExternalType() == CLIENT_VOICE ? "notifymusicqueueentry" : "");
|
||||||
|
|
||||||
|
apply_song(notify, history[index - 1], command_index);
|
||||||
|
notify[command_index]["queue_index"] = -index;
|
||||||
|
|
||||||
|
if(!bulked)
|
||||||
|
this->sendCommand(notify);
|
||||||
|
else
|
||||||
|
command_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
if(!bulked)
|
||||||
|
notify = Command(this->getExternalType() == CLIENT_VOICE ? "notifymusicqueueentry" : "");
|
||||||
|
|
||||||
|
auto song = bot->queue()->currentSong();
|
||||||
|
apply_song(notify, song, command_index);
|
||||||
|
notify[command_index]["queue_index"] = 0;
|
||||||
|
|
||||||
|
if(!bulked)
|
||||||
|
this->sendCommand(notify);
|
||||||
|
else if(song)
|
||||||
|
command_index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
auto queue = bot->queue()->queueEntries();
|
||||||
|
for(int index = 0; index < queue.size(); index++) {
|
||||||
|
if(!bulked)
|
||||||
|
notify = Command(this->getExternalType() == CLIENT_VOICE ? "notifymusicqueueentry" : "");
|
||||||
|
|
||||||
|
apply_song(notify, queue[index], command_index);
|
||||||
|
notify[command_index]["queue_index"] = index + 1;
|
||||||
|
|
||||||
|
if(!bulked)
|
||||||
|
this->sendCommand(notify);
|
||||||
|
else
|
||||||
|
command_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debugMessage(this->getServerId(),"Send: {}",notify.build());
|
||||||
|
if(bulked) {
|
||||||
|
if(command_index > 0) {
|
||||||
|
this->sendCommand(notify);
|
||||||
|
} else return { ErrorType::DBEmpty };
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this->getExternalType() == CLIENT_VOICE) {
|
||||||
|
Command notify("notifymusicqueuefinish");
|
||||||
|
notify["bot_id"] = bot->getClientDatabaseId();
|
||||||
|
this->sendCommand(notify);
|
||||||
|
}
|
||||||
|
|
||||||
|
return command_result{error::ok};
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
command_result ConnectedClient::handleCommandMusicBotQueueAdd(Command& cmd) {
|
||||||
|
return command_result{error::not_implemented}; //FIXME
|
||||||
|
|
||||||
|
/*
|
||||||
|
CMD_REQ_SERVER;
|
||||||
|
CMD_RESET_IDLE;
|
||||||
|
CMD_CHK_AND_INC_FLOOD_POINTS(25);
|
||||||
|
|
||||||
|
auto bot = this->server->musicManager->findBotById(cmd["bot_id"]);
|
||||||
|
if(!bot) return command_result{error::music_invalid_id};
|
||||||
|
PERM_CHECK_CHANNELR(permission::i_client_music_play_power, bot->permissionValue(permission::i_client_music_needed_play_power, bot->currentChannel), this->currentChannel, true);
|
||||||
|
|
||||||
|
MusicClient::loader_t loader;
|
||||||
|
auto& type = cmd[0]["type"];
|
||||||
|
if((type.castable<int>() && type.as<int>() == 0) || type.as<string>() == "yt") {
|
||||||
|
loader = bot->ytLoader(this->getServer());
|
||||||
|
} else if((type.castable<int>() && type.as<int>() == 1) || type.as<string>() == "ffmpeg") {
|
||||||
|
loader = bot->ffmpegLoader(this->getServer());
|
||||||
|
} else if((type.castable<int>() && type.as<int>() == 2) || type.as<string>() == "channel") {
|
||||||
|
loader = bot->channelLoader(this->getServer());
|
||||||
|
} else if((type.castable<int>() && type.as<int>() == -1) || type.as<string>() == "any") {
|
||||||
|
loader = bot->providerLoader(this->getServer(), "");
|
||||||
|
}
|
||||||
|
if(!loader) return command_result{error::music_invalid_action};
|
||||||
|
|
||||||
|
auto entry = bot->queue()->insertEntry(cmd["url"], _this.lock(), loader);
|
||||||
|
if(!entry) return command_result{error::vs_critical};
|
||||||
|
|
||||||
|
this->server->forEachClient([&](shared_ptr<ConnectedClient> client) {
|
||||||
|
client->notifyMusicQueueAdd(bot, entry, bot->queue()->queueEntries().size() - 1, _this.lock());
|
||||||
|
});
|
||||||
|
|
||||||
|
return command_result{error::ok};
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
command_result ConnectedClient::handleCommandMusicBotQueueRemove(Command& cmd) {
|
||||||
|
return command_result{error::not_implemented}; //FIXME
|
||||||
|
|
||||||
|
/*
|
||||||
|
CMD_REQ_SERVER;
|
||||||
|
CMD_RESET_IDLE;
|
||||||
|
CMD_CHK_AND_INC_FLOOD_POINTS(25);
|
||||||
|
|
||||||
|
auto bot = this->server->musicManager->findBotById(cmd["bot_id"]);
|
||||||
|
if(!bot) return command_result{error::music_invalid_id};
|
||||||
|
PERM_CHECK_CHANNELR(permission::i_client_music_play_power, bot->permissionValue(permission::i_client_music_needed_play_power, bot->currentChannel), this->currentChannel, true);
|
||||||
|
|
||||||
|
std::deque<std::shared_ptr<music::SongInfo>> songs;
|
||||||
|
for(int index = 0; index < cmd.bulkCount(); index++) {
|
||||||
|
auto entry = bot->queue()->find_queue(cmd["song_id"]);
|
||||||
|
if(!entry) {
|
||||||
|
if(cmd.hasParm("skip_error")) continue;
|
||||||
|
return command_result{error::database_empty_result};
|
||||||
|
}
|
||||||
|
|
||||||
|
songs.push_back(move(entry));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(const auto& entry : songs)
|
||||||
|
bot->queue()->deleteEntry(dynamic_pointer_cast<music::PlayableSong>(entry));
|
||||||
|
this->server->forEachClient([&](shared_ptr<ConnectedClient> client) {
|
||||||
|
client->notifyMusicQueueRemove(bot, songs, _this.lock());
|
||||||
|
});
|
||||||
|
return command_result{error::ok};
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
command_result ConnectedClient::handleCommandMusicBotQueueReorder(Command& cmd) {
|
||||||
|
return command_result{error::not_implemented}; //FIXME
|
||||||
|
|
||||||
|
/*
|
||||||
|
CMD_REQ_SERVER;
|
||||||
|
CMD_RESET_IDLE;
|
||||||
|
CMD_CHK_AND_INC_FLOOD_POINTS(25);
|
||||||
|
|
||||||
|
auto bot = this->server->musicManager->findBotById(cmd["bot_id"]);
|
||||||
|
if(!bot) return command_result{error::music_invalid_id};
|
||||||
|
PERM_CHECK_CHANNELR(permission::i_client_music_play_power, bot->permissionValue(permission::i_client_music_needed_play_power, bot->currentChannel), this->currentChannel, true);
|
||||||
|
|
||||||
|
auto entry = bot->queue()->find_queue(cmd["song_id"]);
|
||||||
|
if(!entry) return command_result{error::database_empty_result};
|
||||||
|
|
||||||
|
auto order = bot->queue()->changeOrder(entry, cmd["index"]);
|
||||||
|
if(order < 0) return command_result{error::vs_critical};
|
||||||
|
this->server->forEachClient([&](shared_ptr<ConnectedClient> client) {
|
||||||
|
client->notifyMusicQueueOrderChange(bot, entry, order, _this.lock());
|
||||||
|
});
|
||||||
|
return command_result{error::ok};
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
command_result ConnectedClient::handleCommandMusicBotPlaylistAssign(ts::Command &cmd) {
|
||||||
|
CMD_REF_SERVER(ref_server);
|
||||||
|
CMD_RESET_IDLE;
|
||||||
|
CMD_CHK_AND_INC_FLOOD_POINTS(25);
|
||||||
|
|
||||||
|
auto bot = ref_server->musicManager->findBotById(cmd["bot_id"]);
|
||||||
|
if(!bot) return command_result{error::music_invalid_id};
|
||||||
|
if(bot->getOwner() != this->getClientDatabaseId())
|
||||||
|
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::i_client_music_play_power, bot->calculate_permission(permission::i_client_music_needed_play_power, 0));
|
||||||
|
|
||||||
|
auto playlist = ref_server->musicManager->find_playlist(cmd["playlist_id"]);
|
||||||
|
if(!playlist && cmd["playlist_id"] != 0) return command_result{error::playlist_invalid_id};
|
||||||
|
|
||||||
|
if(ref_server->musicManager->find_bot_by_playlist(playlist))
|
||||||
|
return command_result{error::playlist_already_in_use};
|
||||||
|
|
||||||
|
if(playlist && playlist->properties()[property::PLAYLIST_OWNER_DBID] != this->getClientDatabaseId())
|
||||||
|
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::i_playlist_view_power, playlist->permissions()->getPermissionValue(permission::i_playlist_needed_view_power));
|
||||||
|
|
||||||
|
if(!ref_server->musicManager->assign_playlist(bot, playlist))
|
||||||
|
return command_result{error::vs_critical};
|
||||||
|
|
||||||
|
return command_result{error::ok};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
1167
server/src/client/command_handler/server.cpp
Normal file
1167
server/src/client/command_handler/server.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -94,6 +94,7 @@ MusicClient::~MusicClient() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MusicClient::sendCommand(const ts::Command &command, bool low) { }
|
void MusicClient::sendCommand(const ts::Command &command, bool low) { }
|
||||||
|
void MusicClient::sendCommand(const ts::command_builder &command, bool low) { }
|
||||||
|
|
||||||
bool MusicClient::closeConnection(const std::chrono::system_clock::time_point&) {
|
bool MusicClient::closeConnection(const std::chrono::system_clock::time_point&) {
|
||||||
logError(this->getServerId(), "Music manager is forced to disconnect!");
|
logError(this->getServerId(), "Music manager is forced to disconnect!");
|
||||||
|
@ -54,6 +54,8 @@ namespace ts {
|
|||||||
|
|
||||||
//Basic TeaSpeak stuff
|
//Basic TeaSpeak stuff
|
||||||
void sendCommand(const ts::Command &command, bool low) override;
|
void sendCommand(const ts::Command &command, bool low) override;
|
||||||
|
void sendCommand(const ts::command_builder &command, bool low) override;
|
||||||
|
|
||||||
bool disconnect(const std::string &reason) override;
|
bool disconnect(const std::string &reason) override;
|
||||||
bool closeConnection(const std::chrono::system_clock::time_point& = std::chrono::system_clock::time_point()) override;
|
bool closeConnection(const std::chrono::system_clock::time_point& = std::chrono::system_clock::time_point()) override;
|
||||||
void initialize_bot();
|
void initialize_bot();
|
||||||
|
@ -529,6 +529,11 @@ void QueryClient::sendCommand(const ts::Command &command, bool) {
|
|||||||
logTrace(LOG_QUERY, "Send command {}", cmd);
|
logTrace(LOG_QUERY, "Send command {}", cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QueryClient::sendCommand(const ts::command_builder &command, bool) {
|
||||||
|
writeMessage(command.build() + config::query::newlineCharacter);
|
||||||
|
logTrace(LOG_QUERY, "Send command {}", command.build());
|
||||||
|
}
|
||||||
|
|
||||||
void QueryClient::tick(const std::chrono::system_clock::time_point &time) {
|
void QueryClient::tick(const std::chrono::system_clock::time_point &time) {
|
||||||
ConnectedClient::tick(time);
|
ConnectedClient::tick(time);
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ namespace ts {
|
|||||||
void writeMessage(const std::string&);
|
void writeMessage(const std::string&);
|
||||||
|
|
||||||
void sendCommand(const ts::Command &command, bool low = false) override;
|
void sendCommand(const ts::Command &command, bool low = false) override;
|
||||||
|
void sendCommand(const ts::command_builder &command, bool low) override;
|
||||||
|
|
||||||
bool disconnect(const std::string &reason) override;
|
bool disconnect(const std::string &reason) override;
|
||||||
bool closeConnection(const std::chrono::system_clock::time_point& timeout = std::chrono::system_clock::time_point()) override;
|
bool closeConnection(const std::chrono::system_clock::time_point& timeout = std::chrono::system_clock::time_point()) override;
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
#include <src/ShutdownHelper.h>
|
#include <src/ShutdownHelper.h>
|
||||||
#include <ThreadPool/Timer.h>
|
#include <ThreadPool/Timer.h>
|
||||||
|
|
||||||
|
#include "src/client/command_handler/helpers.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
using namespace ts;
|
using namespace ts;
|
||||||
@ -219,7 +221,7 @@ command_result QueryClient::handleCommandLogin(Command& cmd) {
|
|||||||
unique_lock tree_lock(this->server->channel_tree_lock);
|
unique_lock tree_lock(this->server->channel_tree_lock);
|
||||||
if(joined_channel)
|
if(joined_channel)
|
||||||
this->server->client_move(this->ref(), joined_channel, nullptr, "", ViewReasonId::VREASON_USER_ACTION, false, tree_lock);
|
this->server->client_move(this->ref(), joined_channel, nullptr, "", ViewReasonId::VREASON_USER_ACTION, false, tree_lock);
|
||||||
} else if(!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_virtualserver_select_godmode, 1))
|
} else if(!permission::v2::permission_granted(1, this->calculate_permission(permission::b_virtualserver_select_godmode, 1)))
|
||||||
this->server->assignDefaultChannel(this->ref(), true);
|
this->server->assignDefaultChannel(this->ref(), true);
|
||||||
else
|
else
|
||||||
this->update_cached_permissions();
|
this->update_cached_permissions();
|
||||||
@ -271,7 +273,7 @@ command_result QueryClient::handleCommandLogout(Command &) {
|
|||||||
if(joined) {
|
if(joined) {
|
||||||
unique_lock server_channel_w_lock(this->server->channel_tree_lock, defer_lock);
|
unique_lock server_channel_w_lock(this->server->channel_tree_lock, defer_lock);
|
||||||
this->server->client_move(this->ref(), joined, nullptr, "", ViewReasonId::VREASON_USER_ACTION, false, server_channel_w_lock);
|
this->server->client_move(this->ref(), joined, nullptr, "", ViewReasonId::VREASON_USER_ACTION, false, server_channel_w_lock);
|
||||||
} else if(!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_virtualserver_select_godmode, 1)) {
|
} else if(!permission::v2::permission_granted(1, this->calculate_permission(permission::b_virtualserver_select_godmode, 1))) {
|
||||||
this->server->assignDefaultChannel(this->ref(), true);
|
this->server->assignDefaultChannel(this->ref(), true);
|
||||||
} else {
|
} else {
|
||||||
this->update_cached_permissions();
|
this->update_cached_permissions();
|
||||||
@ -310,8 +312,8 @@ command_result QueryClient::handleCommandServerSelect(Command &cmd) {
|
|||||||
if(target->getServerId() != this->query_account->bound_server)
|
if(target->getServerId() != this->query_account->bound_server)
|
||||||
return command_result{error::server_invalid_id, "You're a server bound query, and the target server isn't your origin."};
|
return command_result{error::server_invalid_id, "You're a server bound query, and the target server isn't your origin."};
|
||||||
} else {
|
} else {
|
||||||
auto allowed = target->calculatePermission(permission::PERMTEST_ORDERED, this->getClientDatabaseId(), permission::b_virtualserver_select, this->getType(), nullptr);
|
auto allowed = target->calculate_permission(permission::b_virtualserver_select, this->getClientDatabaseId(), this->getType(), 0);
|
||||||
if(allowed != -1 && allowed <= 0) return command_result{permission::b_virtualserver_select};
|
if(!permission::v2::permission_granted(1, allowed)) return command_result{permission::b_virtualserver_select};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,7 +358,7 @@ command_result QueryClient::handleCommandServerSelect(Command &cmd) {
|
|||||||
this->subscribeChannel(this->server->channelTree->channels(), false, false);
|
this->subscribeChannel(this->server->channelTree->channels(), false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto negated_enforce_join = this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_virtualserver_select_godmode, 1);
|
auto negated_enforce_join = permission::v2::permission_granted(1, this->calculate_permission(permission::b_virtualserver_select_godmode, 1));
|
||||||
if(!negated_enforce_join)
|
if(!negated_enforce_join)
|
||||||
this->server->assignDefaultChannel(this->ref(), true);
|
this->server->assignDefaultChannel(this->ref(), true);
|
||||||
else
|
else
|
||||||
@ -387,8 +389,8 @@ command_result QueryClient::handleCommandLeft(Command&) {
|
|||||||
CMD_REQ_SERVER;
|
CMD_REQ_SERVER;
|
||||||
CMD_REQ_CHANNEL;
|
CMD_REQ_CHANNEL;
|
||||||
CMD_RESET_IDLE;
|
CMD_RESET_IDLE;
|
||||||
|
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_select_godmode, 1);
|
||||||
|
|
||||||
PERM_CHECK_CHANNELR(permission::b_virtualserver_select_godmode, 1, nullptr, 1);
|
|
||||||
unique_lock server_channel_lock(this->server->channel_tree_lock);
|
unique_lock server_channel_lock(this->server->channel_tree_lock);
|
||||||
this->server->client_move(this->ref(), nullptr, nullptr, "leaving", ViewReasonId::VREASON_SERVER_LEFT, true, server_channel_lock);
|
this->server->client_move(this->ref(), nullptr, nullptr, "leaving", ViewReasonId::VREASON_SERVER_LEFT, true, server_channel_lock);
|
||||||
return command_result{error::ok};
|
return command_result{error::ok};
|
||||||
@ -396,7 +398,7 @@ command_result QueryClient::handleCommandLeft(Command&) {
|
|||||||
|
|
||||||
command_result QueryClient::handleCommandServerInfo(Command &) {
|
command_result QueryClient::handleCommandServerInfo(Command &) {
|
||||||
CMD_RESET_IDLE;
|
CMD_RESET_IDLE;
|
||||||
PERM_CHECKR(permission::b_virtualserver_info_view, 1, true);
|
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_info_view, 1);
|
||||||
|
|
||||||
Command cmd("");
|
Command cmd("");
|
||||||
|
|
||||||
@ -409,7 +411,7 @@ command_result QueryClient::handleCommandServerInfo(Command &) {
|
|||||||
cmd["virtualserver_status"] = this->server ? ServerState::string(this->server->state) : "template";
|
cmd["virtualserver_status"] = this->server ? ServerState::string(this->server->state) : "template";
|
||||||
|
|
||||||
|
|
||||||
if(this->server && this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_virtualserver_connectioninfo_view, 1, nullptr, true)) {
|
if(this->server && permission::v2::permission_granted(1, this->calculate_permission(permission::b_virtualserver_connectioninfo_view, 0))) {
|
||||||
auto stats = this->server->getServerStatistics()->statistics();
|
auto stats = this->server->getServerStatistics()->statistics();
|
||||||
auto report = this->server->serverStatistics->dataReport();
|
auto report = this->server->serverStatistics->dataReport();
|
||||||
cmd["connection_bandwidth_sent_last_second_total"] = report.send_second;
|
cmd["connection_bandwidth_sent_last_second_total"] = report.send_second;
|
||||||
@ -478,8 +480,8 @@ command_result QueryClient::handleCommandServerInfo(Command &) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
command_result QueryClient::handleCommandChannelList(Command& cmd) {
|
command_result QueryClient::handleCommandChannelList(Command& cmd) {
|
||||||
PERM_CHECKR(permission::b_virtualserver_channel_list, 1, true);
|
|
||||||
CMD_RESET_IDLE;
|
CMD_RESET_IDLE;
|
||||||
|
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_channel_list, 1);
|
||||||
|
|
||||||
Command result("");
|
Command result("");
|
||||||
|
|
||||||
@ -497,7 +499,7 @@ command_result QueryClient::handleCommandChannelList(Command& cmd) {
|
|||||||
bulk["channel_name"] = channel->name();
|
bulk["channel_name"] = channel->name();
|
||||||
bulk["channel_order"] = channel->channelOrder();
|
bulk["channel_order"] = channel->channelOrder();
|
||||||
bulk["total_clients"] = this->server ? this->server->getClientsByChannel(channel).size() : 0;
|
bulk["total_clients"] = this->server ? this->server->getClientsByChannel(channel).size() : 0;
|
||||||
/* bulk["channel_needed_subscribe_power"] = channel->permissions()->getPermissionValue(permission::PERMTEST_ORDERED, permission::i_channel_needed_subscribe_power, channel, 0); */
|
/* bulk["channel_needed_subscribe_power"] = channel->permissions()->getPermissionValue(permission::i_channel_needed_subscribe_power, channel, 0); */
|
||||||
|
|
||||||
if(cmd.hasParm("flags")){
|
if(cmd.hasParm("flags")){
|
||||||
bulk["channel_flag_default"] = channel->properties()[property::CHANNEL_FLAG_DEFAULT].as<string>();
|
bulk["channel_flag_default"] = channel->properties()[property::CHANNEL_FLAG_DEFAULT].as<string>();
|
||||||
@ -540,7 +542,8 @@ command_result QueryClient::handleCommandChannelList(Command& cmd) {
|
|||||||
|
|
||||||
command_result QueryClient::handleCommandServerList(Command& cmd) {
|
command_result QueryClient::handleCommandServerList(Command& cmd) {
|
||||||
CMD_RESET_IDLE;
|
CMD_RESET_IDLE;
|
||||||
PERM_CHECKR(permission::b_serverinstance_virtualserver_list, 1, true);
|
ACTION_REQUIRES_INSTANCE_PERMISSION(permission::b_serverinstance_virtualserver_list, 1);
|
||||||
|
|
||||||
Command res("");
|
Command res("");
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
@ -573,7 +576,7 @@ command_result QueryClient::handleCommandServerList(Command& cmd) {
|
|||||||
|
|
||||||
command_result QueryClient::handleCommandServerCreate(Command& cmd) {
|
command_result QueryClient::handleCommandServerCreate(Command& cmd) {
|
||||||
CMD_RESET_IDLE;
|
CMD_RESET_IDLE;
|
||||||
PERM_CHECKR(permission::b_virtualserver_create, 1, true);
|
ACTION_REQUIRES_INSTANCE_PERMISSION(permission::b_virtualserver_create, 1);
|
||||||
|
|
||||||
if(serverInstance->getVoiceServerManager()->getState() != ServerManager::STARTED) {
|
if(serverInstance->getVoiceServerManager()->getState() != ServerManager::STARTED) {
|
||||||
return command_result{error::vs_critical, "Server manager isn't started yet or not finished starting"};
|
return command_result{error::vs_critical, "Server manager isn't started yet or not finished starting"};
|
||||||
@ -650,7 +653,7 @@ command_result QueryClient::handleCommandServerCreate(Command& cmd) {
|
|||||||
|
|
||||||
command_result QueryClient::handleCommandServerDelete(Command& cmd) {
|
command_result QueryClient::handleCommandServerDelete(Command& cmd) {
|
||||||
CMD_RESET_IDLE;
|
CMD_RESET_IDLE;
|
||||||
PERM_CHECKR(permission::b_virtualserver_delete, 1, true);
|
ACTION_REQUIRES_INSTANCE_PERMISSION(permission::b_virtualserver_delete, 1);
|
||||||
|
|
||||||
if(serverInstance->getVoiceServerManager()->getState() != ServerManager::STARTED)
|
if(serverInstance->getVoiceServerManager()->getState() != ServerManager::STARTED)
|
||||||
return command_result{error::vs_critical, "Server manager isn't started yet or not finished starting"};
|
return command_result{error::vs_critical, "Server manager isn't started yet or not finished starting"};
|
||||||
@ -664,7 +667,6 @@ command_result QueryClient::handleCommandServerDelete(Command& cmd) {
|
|||||||
command_result QueryClient::handleCommandServerStart(Command& cmd) {
|
command_result QueryClient::handleCommandServerStart(Command& cmd) {
|
||||||
CMD_RESET_IDLE;
|
CMD_RESET_IDLE;
|
||||||
|
|
||||||
PERM_CHECKR(permission::b_virtualserver_start_any, 1, true);
|
|
||||||
if(serverInstance->getVoiceServerManager()->getState() != ServerManager::STARTED)
|
if(serverInstance->getVoiceServerManager()->getState() != ServerManager::STARTED)
|
||||||
return command_result{error::vs_critical, "Server manager isn't started yet or not finished starting"};
|
return command_result{error::vs_critical, "Server manager isn't started yet or not finished starting"};
|
||||||
|
|
||||||
@ -672,10 +674,8 @@ command_result QueryClient::handleCommandServerStart(Command& cmd) {
|
|||||||
if(!server) return command_result{error::server_invalid_id, "invalid bounded server"};
|
if(!server) return command_result{error::server_invalid_id, "invalid bounded server"};
|
||||||
if(server->running()) return command_result{error::server_running, "server already running"};
|
if(server->running()) return command_result{error::server_running, "server already running"};
|
||||||
|
|
||||||
if(server->calculatePermission(permission::PERMTEST_ORDERED, this->getClientDatabaseId(), permission::b_virtualserver_start, ClientType::CLIENT_QUERY, nullptr) != 1) {
|
if(!permission::v2::permission_granted(1, server->calculate_permission(permission::b_virtualserver_start, this->getClientDatabaseId(), ClientType::CLIENT_QUERY, 0)))
|
||||||
if(!this->permissionGranted(permission::PERMTEST_HIGHEST, permission::b_virtualserver_start_any, 1))
|
ACTION_REQUIRES_INSTANCE_PERMISSION(permission::b_virtualserver_start_any, 1);
|
||||||
return command_result{permission::b_virtualserver_start};
|
|
||||||
}
|
|
||||||
|
|
||||||
string err;
|
string err;
|
||||||
if(!server->start(err)) return command_result{error::vs_critical, err};
|
if(!server->start(err)) return command_result{error::vs_critical, err};
|
||||||
@ -684,7 +684,7 @@ command_result QueryClient::handleCommandServerStart(Command& cmd) {
|
|||||||
|
|
||||||
command_result QueryClient::handleCommandServerStop(Command& cmd) {
|
command_result QueryClient::handleCommandServerStop(Command& cmd) {
|
||||||
CMD_RESET_IDLE;
|
CMD_RESET_IDLE;
|
||||||
PERM_CHECKR(permission::b_virtualserver_stop, 1, true);
|
|
||||||
if(serverInstance->getVoiceServerManager()->getState() != ServerManager::STARTED)
|
if(serverInstance->getVoiceServerManager()->getState() != ServerManager::STARTED)
|
||||||
return command_result{error::vs_critical, "Server manager isn't started yet or not finished starting"};
|
return command_result{error::vs_critical, "Server manager isn't started yet or not finished starting"};
|
||||||
|
|
||||||
@ -692,10 +692,8 @@ command_result QueryClient::handleCommandServerStop(Command& cmd) {
|
|||||||
if(!server) return command_result{error::server_invalid_id, "invalid bounded server"};
|
if(!server) return command_result{error::server_invalid_id, "invalid bounded server"};
|
||||||
if(!server->running()) return command_result{error::server_is_not_running, "server is not running"};
|
if(!server->running()) return command_result{error::server_is_not_running, "server is not running"};
|
||||||
|
|
||||||
if(server->calculatePermission(permission::PERMTEST_ORDERED, this->getClientDatabaseId(), permission::b_virtualserver_stop, ClientType::CLIENT_QUERY, nullptr) != 1) {
|
if(!permission::v2::permission_granted(1, server->calculate_permission(permission::b_virtualserver_stop, this->getClientDatabaseId(), ClientType::CLIENT_QUERY, 0)))
|
||||||
if(!this->permissionGranted(permission::PERMTEST_HIGHEST, permission::b_virtualserver_stop_any, 1))
|
ACTION_REQUIRES_INSTANCE_PERMISSION(permission::b_virtualserver_stop_any, 1);
|
||||||
return command_result{permission::b_virtualserver_stop};
|
|
||||||
}
|
|
||||||
|
|
||||||
server->stop("server stopped");
|
server->stop("server stopped");
|
||||||
return command_result{error::ok};
|
return command_result{error::ok};
|
||||||
@ -703,7 +701,7 @@ command_result QueryClient::handleCommandServerStop(Command& cmd) {
|
|||||||
|
|
||||||
|
|
||||||
command_result QueryClient::handleCommandInstanceInfo(Command& cmd) {
|
command_result QueryClient::handleCommandInstanceInfo(Command& cmd) {
|
||||||
PERM_CHECKR(permission::b_serverinstance_info_view, 1, true);
|
ACTION_REQUIRES_INSTANCE_PERMISSION(permission::b_serverinstance_info_view, 1);
|
||||||
|
|
||||||
Command res("");
|
Command res("");
|
||||||
for(const auto& e : serverInstance->properties().list_properties(property::FLAG_INSTANCE_VARIABLE, this->getType() == CLIENT_TEAMSPEAK ? property::FLAG_NEW : (uint16_t) 0))
|
for(const auto& e : serverInstance->properties().list_properties(property::FLAG_INSTANCE_VARIABLE, this->getType() == CLIENT_TEAMSPEAK ? property::FLAG_NEW : (uint16_t) 0))
|
||||||
@ -716,7 +714,7 @@ command_result QueryClient::handleCommandInstanceInfo(Command& cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
command_result QueryClient::handleCommandInstanceEdit(Command& cmd) {
|
command_result QueryClient::handleCommandInstanceEdit(Command& cmd) {
|
||||||
PERM_CHECKR(permission::b_serverinstance_modify_settings, 1, true);
|
ACTION_REQUIRES_INSTANCE_PERMISSION(permission::b_serverinstance_modify_settings, 1);
|
||||||
|
|
||||||
for(const auto &key : cmd[0].keys()){
|
for(const auto &key : cmd[0].keys()){
|
||||||
auto info = property::impl::info<property::InstanceProperties>(key);
|
auto info = property::impl::info<property::InstanceProperties>(key);
|
||||||
@ -739,7 +737,7 @@ command_result QueryClient::handleCommandInstanceEdit(Command& cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
command_result QueryClient::handleCommandHostInfo(Command &) {
|
command_result QueryClient::handleCommandHostInfo(Command &) {
|
||||||
PERM_CHECKR(permission::b_serverinstance_info_view, 1, true);
|
ACTION_REQUIRES_INSTANCE_PERMISSION(permission::b_serverinstance_info_view, 1);
|
||||||
|
|
||||||
Command res("");
|
Command res("");
|
||||||
res["instance_uptime"] = duration_cast<seconds>(system_clock::now() - serverInstance->getStartTimestamp()).count();
|
res["instance_uptime"] = duration_cast<seconds>(system_clock::now() - serverInstance->getStartTimestamp()).count();
|
||||||
@ -774,7 +772,7 @@ command_result QueryClient::handleCommandHostInfo(Command &) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
command_result QueryClient::handleCommandGlobalMessage(Command& cmd) {
|
command_result QueryClient::handleCommandGlobalMessage(Command& cmd) {
|
||||||
PERM_CHECKR(permission::b_serverinstance_textmessage_send, 1, true);
|
ACTION_REQUIRES_INSTANCE_PERMISSION(permission::b_serverinstance_textmessage_send, 1);
|
||||||
|
|
||||||
for(const auto &server : serverInstance->getVoiceServerManager()->serverInstances())
|
for(const auto &server : serverInstance->getVoiceServerManager()->serverInstances())
|
||||||
if(server->running()) server->broadcastMessage(server->getServerRoot(), cmd["msg"]);
|
if(server->running()) server->broadcastMessage(server->getServerRoot(), cmd["msg"]);
|
||||||
@ -801,7 +799,6 @@ command_result QueryClient::handleCommandBindingList(Command& cmd) {
|
|||||||
|
|
||||||
//TODO with mapping!
|
//TODO with mapping!
|
||||||
command_result QueryClient::handleCommandServerSnapshotDeploy(Command& cmd) {
|
command_result QueryClient::handleCommandServerSnapshotDeploy(Command& cmd) {
|
||||||
PERM_CHECKR(permission::b_virtualserver_snapshot_deploy, 1, true);
|
|
||||||
CMD_RESET_IDLE;
|
CMD_RESET_IDLE;
|
||||||
|
|
||||||
auto start = system_clock::now();
|
auto start = system_clock::now();
|
||||||
@ -809,8 +806,11 @@ command_result QueryClient::handleCommandServerSnapshotDeploy(Command& cmd) {
|
|||||||
string host = "0.0.0.0";
|
string host = "0.0.0.0";
|
||||||
uint16_t port = 0;
|
uint16_t port = 0;
|
||||||
if(this->server) {
|
if(this->server) {
|
||||||
|
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_snapshot_deploy, 1);
|
||||||
host = this->server->properties()[property::VIRTUALSERVER_HOST].as<string>();
|
host = this->server->properties()[property::VIRTUALSERVER_HOST].as<string>();
|
||||||
port = this->server->properties()[property::VIRTUALSERVER_PORT].as<uint16_t>();
|
port = this->server->properties()[property::VIRTUALSERVER_PORT].as<uint16_t>();
|
||||||
|
} else {
|
||||||
|
ACTION_REQUIRES_INSTANCE_PERMISSION(permission::b_virtualserver_snapshot_deploy, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto hash = cmd["hash"].string();
|
auto hash = cmd["hash"].string();
|
||||||
@ -862,7 +862,7 @@ command_result QueryClient::handleCommandServerSnapshotDeploy(Command& cmd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
command_result QueryClient::handleCommandServerSnapshotCreate(Command& cmd) {
|
command_result QueryClient::handleCommandServerSnapshotCreate(Command& cmd) {
|
||||||
PERM_CHECKR(permission::b_virtualserver_snapshot_create, 1, true);
|
ACTION_REQUIRES_GLOBAL_PERMISSION(permission::b_virtualserver_snapshot_create, 1);
|
||||||
CMD_RESET_IDLE;
|
CMD_RESET_IDLE;
|
||||||
CMD_REQ_SERVER;
|
CMD_REQ_SERVER;
|
||||||
|
|
||||||
@ -887,7 +887,7 @@ command_result QueryClient::handleCommandServerSnapshotCreate(Command& cmd) {
|
|||||||
|
|
||||||
extern bool mainThreadActive;
|
extern bool mainThreadActive;
|
||||||
command_result QueryClient::handleCommandServerProcessStop(Command& cmd) {
|
command_result QueryClient::handleCommandServerProcessStop(Command& cmd) {
|
||||||
PERM_CHECKR(permission::b_serverinstance_stop, 1, true);
|
ACTION_REQUIRES_INSTANCE_PERMISSION(permission::b_serverinstance_stop, 1);
|
||||||
|
|
||||||
if(cmd[0].has("type")) {
|
if(cmd[0].has("type")) {
|
||||||
if(cmd["type"] == "cancel") {
|
if(cmd["type"] == "cancel") {
|
||||||
|
@ -47,8 +47,7 @@ VoiceClient::~VoiceClient() {
|
|||||||
memtrack::freed<VoiceClient>(this);
|
memtrack::freed<VoiceClient>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceClient::sendCommand0(const ts::Command &command, bool low, bool direct, std::unique_ptr<threads::Future<bool>> listener) {
|
void VoiceClient::sendCommand0(const std::string_view& cmd, bool low, bool direct, std::unique_ptr<threads::Future<bool>> listener) {
|
||||||
auto cmd = command.build();
|
|
||||||
if(cmd.empty()) {
|
if(cmd.empty()) {
|
||||||
logCritical(this->getServerId(), "{} Attempted to send an empty command!", CLIENT_STR_LOG_PREFIX);
|
logCritical(this->getServerId(), "{} Attempted to send an empty command!", CLIENT_STR_LOG_PREFIX);
|
||||||
return;
|
return;
|
||||||
@ -65,7 +64,7 @@ void VoiceClient::sendCommand0(const ts::Command &command, bool low, bool direct
|
|||||||
this->connection->sendPacket(packet, false, direct);
|
this->connection->sendPacket(packet, false, direct);
|
||||||
|
|
||||||
#ifdef PKT_LOG_CMD
|
#ifdef PKT_LOG_CMD
|
||||||
logTrace(this->getServerId(), "{}[Command][Server -> Client] Sending command {}. Command low: {}. Full command: {}", CLIENT_STR_LOG_PREFIX, command.command(), low, cmd);
|
logTrace(this->getServerId(), "{}[Command][Server -> Client] Sending command {}. Command low: {}. Full command: {}", CLIENT_STR_LOG_PREFIX, cmd.substr(0, cmd.find(' ')), low, cmd);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
void VoiceClient::sendAcknowledge(uint16_t packetId, bool low) {
|
void VoiceClient::sendAcknowledge(uint16_t packetId, bool low) {
|
||||||
@ -173,7 +172,7 @@ bool VoiceClient::disconnect(ts::ViewReasonId reason_id, const std::string &reas
|
|||||||
|
|
||||||
self->closeConnection();
|
self->closeConnection();
|
||||||
}, system_clock::now() + seconds(5));
|
}, system_clock::now() + seconds(5));
|
||||||
this->sendCommand0(cmd, false, false, std::move(listener));
|
this->sendCommand0(cmd.build(), false, false, std::move(listener));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,9 +54,11 @@ namespace ts {
|
|||||||
bool disconnect(const std::string&) override;
|
bool disconnect(const std::string&) override;
|
||||||
bool disconnect(ViewReasonId /* reason type */, const std::string& /* reason */, const std::shared_ptr<ts::server::ConnectedClient>& /* invoker */, bool /* notify viewer */);
|
bool disconnect(ViewReasonId /* reason type */, const std::string& /* reason */, const std::shared_ptr<ts::server::ConnectedClient>& /* invoker */, bool /* notify viewer */);
|
||||||
|
|
||||||
virtual void sendCommand(const ts::Command &command, bool low = false) { return this->sendCommand0(command, low); }
|
virtual void sendCommand(const ts::Command &command, bool low = false) { return this->sendCommand0(command.build(), low); }
|
||||||
|
virtual void sendCommand(const ts::command_builder &command, bool low) { return this->sendCommand0(command.build(), low); }
|
||||||
|
|
||||||
/* Note: Order is only guaranteed if progressDirectly is on! */
|
/* Note: Order is only guaranteed if progressDirectly is on! */
|
||||||
virtual void sendCommand0(const ts::Command &command, bool low = false, bool progressDirectly = false, std::unique_ptr<threads::Future<bool>> listener = nullptr);
|
virtual void sendCommand0(const std::string_view& /* data */, bool low = false, bool progressDirectly = false, std::unique_ptr<threads::Future<bool>> listener = nullptr);
|
||||||
virtual void sendAcknowledge(uint16_t packetId, bool low = false);
|
virtual void sendAcknowledge(uint16_t packetId, bool low = false);
|
||||||
|
|
||||||
connection::VoiceClientConnection* getConnection(){ return connection; }
|
connection::VoiceClientConnection* getConnection(){ return connection; }
|
||||||
|
@ -153,7 +153,7 @@ ts::command_result VoiceClient::handleCommandClientInitIv(Command& command) {
|
|||||||
} else {
|
} else {
|
||||||
this->handshake.state = HandshakeState::SUCCEEDED; /* we're doing the verify via TeamSpeak */
|
this->handshake.state = HandshakeState::SUCCEEDED; /* we're doing the verify via TeamSpeak */
|
||||||
}
|
}
|
||||||
this->sendCommand0(initivexpand, false, true); //If we setup the encryption now
|
this->sendCommand0(initivexpand.build(), false, true); //If we setup the encryption now
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -157,6 +157,19 @@ void WebClient::sendCommand(const ts::Command &command, bool low) {
|
|||||||
this->sendJson(value);
|
this->sendJson(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebClient::sendCommand(const ts::command_builder &command, bool low) {
|
||||||
|
#if false
|
||||||
|
Json::Value value{};
|
||||||
|
value["type"] = "command2";
|
||||||
|
value["payload"] = command.build();
|
||||||
|
this->sendJson(value);
|
||||||
|
#else
|
||||||
|
auto data = command.build();
|
||||||
|
Command parsed_command = Command::parse(pipes::buffer_view{data.data(), data.length()}, true, false);
|
||||||
|
this->sendCommand(parsed_command, low);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
bool WebClient::closeConnection(const std::chrono::system_clock::time_point& timeout) {
|
bool WebClient::closeConnection(const std::chrono::system_clock::time_point& timeout) {
|
||||||
bool flushing = timeout.time_since_epoch().count() > 0;
|
bool flushing = timeout.time_since_epoch().count() > 0;
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ namespace ts {
|
|||||||
|
|
||||||
void sendJson(const Json::Value&);
|
void sendJson(const Json::Value&);
|
||||||
void sendCommand(const ts::Command &command, bool low = false) override;
|
void sendCommand(const ts::Command &command, bool low = false) override;
|
||||||
|
void sendCommand(const ts::command_builder &command, bool low) override;
|
||||||
|
|
||||||
bool disconnect(const std::string &reason) override;
|
bool disconnect(const std::string &reason) override;
|
||||||
bool closeConnection(const std::chrono::system_clock::time_point& timeout = std::chrono::system_clock::time_point()) override;
|
bool closeConnection(const std::chrono::system_clock::time_point& timeout = std::chrono::system_clock::time_point()) override;
|
||||||
|
2
shared
2
shared
@ -1 +1 @@
|
|||||||
Subproject commit d42ec40a58892f4c7ff1da6dd4e69df94e2aa848
|
Subproject commit 23a9385afebbbdb2cba88c5ea5f84daf4c85acc4
|
Loading…
Reference in New Issue
Block a user