diff --git a/git-teaspeak b/git-teaspeak index 535d63f..6afc5f0 160000 --- a/git-teaspeak +++ b/git-teaspeak @@ -1 +1 @@ -Subproject commit 535d63f039b3e0b0559e7e09a5c80b04111fe93f +Subproject commit 6afc5f0a4fbd9b8a4b8867f14ce2c5b2bf47bfbd diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 55c7655..4284dac 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -85,6 +85,7 @@ set(SERVER_SOURCE_FILES src/DatabaseHelper.cpp src/manager/LetterManager.cpp + src/manager/PermissionNameManager.cpp tomcryptTest.cpp @@ -184,9 +185,49 @@ target_link_libraries(PermHelper jemalloc ) +add_executable(PermMapHelper helpers/PermMapGen.cpp) +target_link_libraries(PermMapHelper + ${LIBRARY_PATH_ED255} + + TeaSpeak #Static + TeaLicenseHelper #Static + TeaMusic #Static + ${LIBRARY_PATH_THREAD_POOL} #Static + ${LIBRARY_PATH_TERMINAL} #Static + ${LIBRARY_PATH_VARIBALES} + ${LIBRARY_PATH_YAML} + pthread + stdc++fs + ${LIBEVENT_PATH}/libevent.a + ${LIBEVENT_PATH}/libevent_pthreads.a + ${LIBRARY_PATH_OPUS} + ${LIBRARY_PATH_JSON} + ${LIBRARY_PATH_PROTOBUF} + + #${LIBWEBRTC_LIBRARIES} #ATTENTIAN! WebRTC does not work with crypto! (Already contains a crypto version) + ${LIBRARY_TOM_CRYPT} + ${LIBRARY_TOM_MATH} + + #We're forsed to use boringssl caused by the fact that boringssl is already within webrtc! + + #Require a so + sqlite3 + + ${LIBRARY_PATH_BREAKPAD} + ${LIBRARY_PATH_JDBC} + ${LIBRARY_PATH_PROTOBUF} + + ${LIBRARY_PATH_DATA_PIPES} + ${LIBRARY_PATH_BORINGSSL_SSL} + ${LIBRARY_PATH_BORINGSSL_CRYPTO} + dl + jemalloc + ) + + SET(CPACK_PACKAGE_VERSION_MAJOR "1") SET(CPACK_PACKAGE_VERSION_MINOR "3") -SET(CPACK_PACKAGE_VERSION_PATCH "23") +SET(CPACK_PACKAGE_VERSION_PATCH "24") if(BUILD_TYPE_NAME EQUAL OFF) SET(CPACK_PACKAGE_VERSION_DATA "beta") elseif(BUILD_TYPE_NAME STREQUAL "") diff --git a/server/helpers/PermMapGen.cpp b/server/helpers/PermMapGen.cpp new file mode 100644 index 0000000..a0cebd5 --- /dev/null +++ b/server/helpers/PermMapGen.cpp @@ -0,0 +1,82 @@ +#include +#include +#include +#include + +#include /* required from permission manager */ +#include "log/LogUtils.h" +#include "Definitions.h" +#include "PermissionManager.h" + +using namespace std; +using namespace ts; + +/* Took from the permission mapper within the TeaSpeakServer */ +enum PermissionMapGroup { + MIN, + TS3 = MIN, + TEAWEB, + TEACLIENT, + QUERY, + MAX +}; + +std::map group_names = { + {PermissionMapGroup::TS3, "TeamSpeak 3"}, + {PermissionMapGroup::TEAWEB, "TeaSpeak-Web"}, + {PermissionMapGroup::TEACLIENT, "TeaSpeak-Client"}, + {PermissionMapGroup::QUERY, "Query"} +}; + +//TODO: Does it work with a space at the end? +#define I "\x5f\xcc\xb2" /* an underscore with an non-spacing underscore */ +std::map replacements = { + {"_music", I "music"}, + {"_hwid", I "hwid" }, + {"_playlist", I "playlist"} +}; + +std::string replace_all(std::string str, const std::string& from, const std::string& to) { + size_t start_pos = 0; + while((start_pos = str.find(from, start_pos)) != std::string::npos) { + str.replace(start_pos, from.length(), to); + start_pos += to.length(); // Handles case where 'to' is a substring of 'from' + } + return str; +} + + +int main(int argc, char** argv) { + ofstream of("permission_mapping.txt"); + + of << "# This is a auto generated template file!" << endl; + of << "# DO NOT EDIT IF YOU'RE NOT SURE WHAT YOU'RE DOING!" << endl; + of << "# Syntax:" << endl; + of << "# group: -> group id values: 0 := TS3 | 1 := TeaWeb | 2 := TeaClient | 3 := Query " << endl; + of << "# mapping::" << endl; + of << "# Note: Be aware of spaces and line endings. The TeaSpeakServer does not trim the values!" << endl; + of << "#" << endl; + + + for(PermissionMapGroup type = PermissionMapGroup::MIN; type < PermissionMapGroup::MAX; (*(int*) &type)++) { + of << "# Begin mapping for group " << (int) type << " (" << group_names[type] << ")" << endl; + of << "group:" << (int) type << endl; + + if(type == PermissionMapGroup::TS3) { + for(const auto& permission : permission::availablePermissions) { + if(!permission->clientSupported) + continue; + + auto value = permission->name; + for(auto& replacement : replacements) + value = replace_all(value, replacement.first, replacement.second); + of << "mapping:" << permission->name << ":" << value << endl; + } + } else { + of << "# No mapping required here. You're of course free to add stuff here." << endl; + } + of << "# End mapping of group" << endl; + } + + of.close(); +} \ No newline at end of file diff --git a/server/src/Configuration.cpp b/server/src/Configuration.cpp index 086fdf5..b063f7e 100644 --- a/server/src/Configuration.cpp +++ b/server/src/Configuration.cpp @@ -39,6 +39,7 @@ std::string config::database::sqlite::sync_mode; std::shared_ptr config::license; std::shared_ptr config::license_original; bool config::experimental_31 = false; +std::string config::permission_mapping_file; bool ts::config::binding::enforce_default_voice_host = false; std::string ts::config::binding::DefaultVoiceHost; @@ -887,6 +888,12 @@ std::deque> config::create_bindings() { BIND_STRING(config::music::command_prefix, "."); ADD_DESCRIPTION("The default channel chat command prefix"); } + { + CREATE_BINDING("permission_mapping", 0); + BIND_STRING(config::permission_mapping_file, "resources/permission_mapping.txt"); + ADD_DESCRIPTION("Mapping for the permission names"); + ADD_SENSITIVE(); + } } { BIND_GROUP(log) diff --git a/server/src/Configuration.h b/server/src/Configuration.h index 69b89db..092515f 100644 --- a/server/src/Configuration.h +++ b/server/src/Configuration.h @@ -46,6 +46,7 @@ namespace ts { extern std::shared_ptr license_original; extern bool experimental_31; + extern std::string permission_mapping_file; namespace binding { extern bool enforce_default_voice_host; diff --git a/server/src/InstanceHandler.cpp b/server/src/InstanceHandler.cpp index 103b91b..f444267 100644 --- a/server/src/InstanceHandler.cpp +++ b/server/src/InstanceHandler.cpp @@ -12,6 +12,7 @@ #include "src/server/QueryServer.h" #include "src/server/file/FileServer.h" #include "SignalHandler.h" +#include "src/manager/PermissionNameMapper.h" #include #include "ShutdownHelper.h" #include @@ -228,8 +229,15 @@ inline sockaddr_in* resolveAddress(const string& host, uint16_t port) { bool InstanceHandler::startInstance() { if (this->active) return false; active = true; + string errorMessage; + this->web_list->enabled = ts::config::server::enable_teamspeak_weblist; + this->permission_mapper = make_shared(); + if(!this->permission_mapper->initialize(config::permission_mapping_file, errorMessage)) { + logCritical(LOG_INSTANCE, "Failed to initialize permission name mapping from file {}: {}", config::permission_mapping_file, errorMessage); + return false; + } this->sslMgr = new ssl::SSLManager(); if(!this->sslMgr->initialize()) { logCritical("Failed to initialize ssl manager."); @@ -264,7 +272,6 @@ bool InstanceHandler::startInstance() { } } - string errorMessage; queryServer = new ts::server::QueryServer(this->getSql()); { auto server_query = queryServer->find_query_account_by_name("serveradmin"); diff --git a/server/src/InstanceHandler.h b/server/src/InstanceHandler.h index 0f63226..8fac8bb 100644 --- a/server/src/InstanceHandler.h +++ b/server/src/InstanceHandler.h @@ -15,6 +15,10 @@ namespace ts { class WebListManager; } + namespace permission { + class PermissionNameMapper; + } + namespace server { class InstanceHandler { public: @@ -62,6 +66,8 @@ namespace ts { std::shared_ptr getDefaultServerProperties() { return this->default_server_properties; } std::shared_ptr getWebIoLoop() { return this->web_event_loop; } std::shared_ptr getWebList() { return this->web_list; } + + std::shared_ptr getPermissionMapper() { return this->permission_mapper; } private: std::mutex activeLock; std::condition_variable activeCon; @@ -101,6 +107,7 @@ namespace ts { std::shared_ptr statistics = nullptr; std::shared_ptr tick_manager = nullptr; + std::shared_ptr permission_mapper = nullptr; std::shared_ptr teamspeak_license = nullptr; threads::Mutex lock_tick; diff --git a/server/src/client/ConnectedClientCommandHandler.cpp b/server/src/client/ConnectedClientCommandHandler.cpp index 5b328ba..4c42564 100644 --- a/server/src/client/ConnectedClientCommandHandler.cpp +++ b/server/src/client/ConnectedClientCommandHandler.cpp @@ -17,6 +17,7 @@ #include "music/MusicClient.h" #include "query/QueryClient.h" #include "../weblist/WebListManager.h" +#include "../manager/PermissionNameMapper.h" #include #include #include @@ -42,6 +43,7 @@ extern ts::server::InstanceHandler *serverInstance; #define QUERY_PASSWORD_LENGTH 12 +//TODO: Map permsid! #define PARSE_PERMISSION(cmd) \ permission::PermissionType permType = permission::PermissionType::unknown; \ bool grant = false; \ @@ -830,10 +832,10 @@ CommandResult ConnectedClient::handleCommandChannelUnsubscribeAll(Command &cmd) CommandResult ConnectedClient::handleCommandPermissionList(Command &cmd) { CMD_CHK_AND_INC_FLOOD_POINTS(5); - static std::string permission_list_string; + static std::string permission_list_string[ClientType::MAX]; static std::mutex permission_list_string_lock; - static auto build_permission_list = [](const std::string& command) { + static auto build_permission_list = [](const std::string& command, const ClientType& type) { Command list_builder(command); int index = 0; for (auto group : permission::availableGroups) @@ -843,28 +845,31 @@ CommandResult ConnectedClient::handleCommandPermissionList(Command &cmd) { std::sort(avPerms.begin(), avPerms.end(), [](const std::shared_ptr &a, const std::shared_ptr &b) { return a->type < b->type; }); + + auto mapper = serverInstance->getPermissionMapper(); for (const auto& permission : avPerms) { if (!permission->clientSupported) continue; auto &blk = list_builder[index++]; - blk["permname"] = permission->name; + blk["permname"] = mapper->permission_name(type, permission->type); blk["permdesc"] = permission->description; blk["permid"] = permission->type; } return list_builder; }; - if(this->getType() == CLIENT_TEASPEAK || this->getType() == CLIENT_TEAMSPEAK || this->getType() == CLIENT_QUERY) { + auto type = this->getType(); + if(type == CLIENT_TEASPEAK || type == CLIENT_TEAMSPEAK || type == CLIENT_QUERY) { Command response(this->getExternalType() == CLIENT_TEAMSPEAK ? "notifypermissionlist" : ""); { lock_guard lock(permission_list_string_lock); - if(permission_list_string.empty()) - permission_list_string = build_permission_list("").build(); - response[0][""] = permission_list_string; + if(permission_list_string[type].empty()) + permission_list_string[type] = build_permission_list("", type).build(); + response[0][""] = permission_list_string[type]; } this->sendCommand(response); } else { - this->sendCommand(build_permission_list(this->getExternalType() == CLIENT_TEAMSPEAK ? "notifypermissionlist" : "")); + this->sendCommand(build_permission_list(this->getExternalType() == CLIENT_TEAMSPEAK ? "notifypermissionlist" : "", type)); } return CommandResult::Success; } @@ -2255,12 +2260,14 @@ CommandResult ConnectedClient::handleCommandChannelPermList(Command &cmd) { int index = 0; result["cid"] = channel->channelId(); + auto permission_mapper = serverInstance->getPermissionMapper(); + auto type = this->getType(); auto permission_manager = channel->permissions(); for (const auto &permission_data : permission_manager->permissions()) { auto& permission = std::get<1>(permission_data); if(permission.flags.value_set) { if(sids) { - result[index]["permsid"] = permission::resolvePermissionData(std::get<0>(permission_data))->name; + result[index]["permsid"] = permission_mapper->permission_name(type, std::get<0>(permission_data)); } else { result[index]["permid"] = std::get<0>(permission_data); } @@ -2272,7 +2279,7 @@ CommandResult ConnectedClient::handleCommandChannelPermList(Command &cmd) { } if(permission.flags.grant_set) { if(sids) { - result[index]["permsid"] = permission::resolvePermissionData(std::get<0>(permission_data))->grant_name; + result[index]["permsid"] = permission_mapper->permission_name_grant(type, std::get<0>(permission_data)); } else { result[index]["permid"] = (uint16_t) (std::get<0>(permission_data) | PERM_ID_GRANT); } @@ -4904,11 +4911,14 @@ CommandResult ConnectedClient::handleCommandChannelClientPermList(Command &cmd) res[index]["cldbid"] = cmd["cldbid"].as(); auto sids = cmd.hasParm("permsid"); + auto permission_mapper = serverInstance->getPermissionMapper(); + auto type = this->getType(); + for (const auto &permission_data : permissions) { auto& permission = std::get<1>(permission_data); if(permission.flags.value_set) { if (sids) - res[index]["permsid"] = permission::resolvePermissionData(get<0>(permission_data))->name; + res[index]["permsid"] = permission_mapper->permission_name(type, get<0>(permission_data)); else res[index]["permid"] = get<0>(permission_data); res[index]["permvalue"] = permission.values.value; @@ -4921,7 +4931,7 @@ CommandResult ConnectedClient::handleCommandChannelClientPermList(Command &cmd) if(permission.flags.grant_set) { if (sids) - res[index]["permsid"] = permission::resolvePermissionData(get<0>(permission_data))->grant_name; + res[index]["permsid"] = permission_mapper->permission_name_grant(type, get<0>(permission_data)); else res[index]["permid"] = (get<0>(permission_data) | PERM_ID_GRANT); res[index]["permvalue"] = permission.values.grant; @@ -5349,12 +5359,14 @@ CommandResult ConnectedClient::handleCommandPermGet(Command &cmd) { Command res(""); deque requrested; + auto permission_mapper = serverInstance->getPermissionMapper(); + auto type = this->getType(); for (int index = 0; index < cmd.bulkCount(); index++) { permission::PermissionType permType = permission::unknown; if (cmd[index].has("permid")) permType = cmd[index]["permid"].as(); else if (cmd[index].has("permsid")) - permType = permission::resolvePermissionData(cmd[index]["permsid"].as())->type; + permType = permission::resolvePermissionData(cmd[index]["permsid"].as())->type; //TODO: Map the other way around! if (permission::resolvePermissionData(permType)->type == permission::PermissionType::unknown) return {findError("parameter_invalid"), "could not resolve permission"}; requrested.push_back(permType); @@ -5362,7 +5374,7 @@ CommandResult ConnectedClient::handleCommandPermGet(Command &cmd) { int index = 0; for(const auto& entry : this->permissionValues(permission::PERMTEST_ORDERED, requrested, this->currentChannel)) { - res[index]["permsid"] = permission::resolvePermissionData(entry.first)->name; + res[index]["permsid"] = permission_mapper->permission_name(type, entry.first);; res[index]["permid"] = entry.first; res[index++]["permvalue"] = entry.second; } @@ -5372,7 +5384,7 @@ CommandResult ConnectedClient::handleCommandPermGet(Command &cmd) { } CommandResult ConnectedClient::handleCommandPermIdGetByName(Command &cmd) { - auto found = permission::resolvePermissionData(cmd["permsid"].as()); + auto found = permission::resolvePermissionData(cmd["permsid"].as()); //TODO: Map the other way around Command res(""); res["permid"] = found->type; this->sendCommand(res); @@ -5409,7 +5421,7 @@ CommandResult ConnectedClient::handleCommandPermFind(Command &cmd) { if(permission->type == permission::PermissionType::unknown) return {findError("parameter_invalid"), "could not resolve permission (id=" + cmd[index]["permid"].string() + ")"}; } else if (cmd[index].has("permsid")) { - permission = permission::resolvePermissionData(cmd[index]["permsid"].as()); + permission = permission::resolvePermissionData(cmd[index]["permsid"].as()); //TODO: Map the other way around granted = permission->grant_name == cmd[index]["permsid"].as(); if(permission->type == permission::PermissionType::unknown) diff --git a/server/src/client/ConnectedClientNotifyHandler.cpp b/server/src/client/ConnectedClientNotifyHandler.cpp index 9b6fab8..70aa970 100644 --- a/server/src/client/ConnectedClientNotifyHandler.cpp +++ b/server/src/client/ConnectedClientNotifyHandler.cpp @@ -7,6 +7,7 @@ #include "../server/VoiceServer.h" #include "../InstanceHandler.h" #include "../server/QueryServer.h" +#include "../manager/PermissionNameMapper.h" #include "music/MusicClient.h" #include #include @@ -72,16 +73,17 @@ bool ConnectedClient::notifyGroupPermList(const std::shared_ptr& group, b int index = 0; auto permissions = group->permissions()->permissions(); + auto permission_mapper = serverInstance->getPermissionMapper(); + auto client_type = this->getType(); for (const auto &permission_data : permissions) { auto& permission = get<1>(permission_data); if(!permission.flags.value_set) continue; - auto type = permission::resolvePermissionData(get<0>(permission_data)); if(as_sid) { - cmd[index]["permsid"] = type->name; + cmd[index]["permsid"] = permission_mapper->permission_name(client_type, get<0>(permission_data)); } else { - cmd[index]["permid"] = (uint16_t) type->type; + cmd[index]["permid"] = (uint16_t) get<0>(permission_data); } cmd[index]["permvalue"] = permission.values.value; cmd[index]["permnegated"] = permission.flags.negate; @@ -93,11 +95,10 @@ bool ConnectedClient::notifyGroupPermList(const std::shared_ptr& group, b if(!permission.flags.grant_set) continue; - auto type = permission::resolvePermissionData(get<0>(permission_data)); if(as_sid) { - cmd[index]["permsid"] = type->grant_name; + cmd[index]["permsid"] = permission_mapper->permission_name_grant(client_type, get<0>(permission_data)); } else { - cmd[index]["permid"] = (uint16_t) (type->type | PERM_ID_GRANT); + cmd[index]["permid"] = (uint16_t) (get<0>(permission_data) | PERM_ID_GRANT); } cmd[index]["permvalue"] = permission.values.grant; cmd[index]["permnegated"] = permission.flags.negate; @@ -122,11 +123,13 @@ bool ConnectedClient::notifyClientPermList(ClientDbId cldbid, const std::shared_ int index = 0; res[index]["cldbid"] = cldbid; + auto permission_mapper = serverInstance->getPermissionMapper(); + auto client_type = this->getType(); for (const auto &permission_data : permissions) { auto& permission = std::get<1>(permission_data); if(permission.flags.value_set) { if (perm_sids) - res[index]["permsid"] = permission::resolvePermissionData(get<0>(permission_data))->name; + res[index]["permsid"] = permission_mapper->permission_name(client_type, get<0>(permission_data)); else res[index]["permid"] = get<0>(permission_data); res[index]["permvalue"] = permission.values.value; @@ -139,7 +142,7 @@ bool ConnectedClient::notifyClientPermList(ClientDbId cldbid, const std::shared_ if(permission.flags.grant_set) { if (perm_sids) - res[index]["permsid"] = permission::resolvePermissionData(get<0>(permission_data))->grant_name; + res[index]["permsid"] = permission_mapper->permission_name_grant(client_type, get<0>(permission_data)); else res[index]["permid"] = (get<0>(permission_data) | PERM_ID_GRANT); res[index]["permvalue"] = permission.values.grant; diff --git a/server/src/manager/PermissionNameManager.cpp b/server/src/manager/PermissionNameManager.cpp new file mode 100644 index 0000000..b87c2dd --- /dev/null +++ b/server/src/manager/PermissionNameManager.cpp @@ -0,0 +1,122 @@ +#include +#include +#include +#include "PermissionNameMapper.h" + +using namespace ts::permission; +using namespace std; +namespace fs = std::experimental::filesystem; + +PermissionNameMapper::PermissionNameMapper() {} +PermissionNameMapper::~PermissionNameMapper() {} + + +std::string PermissionNameMapper::permission_name(const Type::value& type, const ts::permission::PermissionType &permission) const { + const static std::string unknown = "unknown"; + + if(type < 0 || type > Type::MAX) + return unknown; + + if(permission < 0 || permission >= PermissionType::permission_id_max) + return unknown; + + return this->mapping[type][permission].mapped_name; +} + +std::string PermissionNameMapper::permission_name_grant(const Type::value& type, const ts::permission::PermissionType &permission) const { + const static std::string unknown = "unknown"; + + if(type < 0 || type > Type::MAX) + return unknown; + + if(permission < 0 || permission >= PermissionType::permission_id_max) + return unknown; + + return this->mapping[type][permission].grant_name; +} + +bool PermissionNameMapper::initialize(const std::string &file, std::string &error) { + auto file_path = fs::u8path(file); + if(!fs::exists(file)) { + error = "file does not exists"; + return false; + } + + ifstream istream(file_path); + if(!istream.good()) { + error = "failed to open file"; + return false; + } + + array, PermissionType::permission_id_max> mapping; + + string line; + auto current_type = Type::MAX; + size_t line_index = 0; + + std::string key, value; + while(istream) { + line.clear(); + getline(istream, line); + line_index++; + if(line.empty() || line[0] == '#') + continue; + + auto seperator = line.find(':'); + if(seperator == -1) { + logWarning(LOG_INSTANCE, "Invalid permission mapping line {}: {}", line_index, line); + continue; + } + + key = line.substr(0, seperator); + value = line.substr(seperator + 1); + + if(key == "group") { + try { + auto index = stol(value); + if(index < 0 || index >= Type::MAX) { + logWarning(LOG_INSTANCE, "Invalid permission group at {}. Value is not in bounds: {}", line_index, line); + continue; + } + + current_type = (Type::value) index; + continue; + } catch(std::exception& ex) { + logWarning(LOG_INSTANCE, "Invalid permission group at {}. Value is not a number: {}", line_index, line); + continue; + } + } else if(key == "mapping") { + if(current_type == Type::MAX) { + logWarning(LOG_INSTANCE, "Invalid permission mapping entry at line {} (No group set): {}", line_index, line); + continue; + } + seperator = value.find(':'); + if(seperator == -1) { + logWarning(LOG_INSTANCE, "Invalid permission mapping entry at line {} (Missing colon): {}", line_index, line); + continue; + } + key = value.substr(0, seperator); + value = value.substr(seperator + 1); + + mapping[current_type][key] = value; + } else { + logWarning(LOG_INSTANCE, "Invalid permission mapping line at {}. Key is unknown: {}", line_index, line); + continue; + } + } + + /* lets build the index */ + for(Type::value type = Type::MIN; type < Type::MAX; (*(int*) &type)++) { + auto& array = this->mapping[type]; + auto& map = mapping[type]; + + for(PermissionType permission = PermissionType::permission_id_min; permission < PermissionType::permission_id_max; (*(uint16_t *)&permission)++) { + auto data = permission::resolvePermissionData(permission); + + array[permission].mapped_name = map.count(data->name) > 0 ? map[data->name] : data->name; + array[permission].grant_name = "i_needed_modify_power_" + array[permission].mapped_name.substr(2); + } + } + + return true; +} \ No newline at end of file diff --git a/server/src/manager/PermissionNameMapper.h b/server/src/manager/PermissionNameMapper.h new file mode 100644 index 0000000..d8a5dd2 --- /dev/null +++ b/server/src/manager/PermissionNameMapper.h @@ -0,0 +1,60 @@ +#pragma once + +#include +#include "PermissionManager.h" +#include "Definitions.h" + +namespace ts { + namespace permission { + class PermissionNameMapper { + public: + struct Type { + enum value { + MIN, + TS3 = MIN, + TEAWEB, + TEACLIENT, + QUERY, + MAX + }; + + inline static value from_client_type(const server::ClientType& client) { + if(client == server::ClientType::CLIENT_TEAMSPEAK) + return value::TS3; + + if(client == server::ClientType::CLIENT_TEASPEAK) + return value::TEACLIENT; + + if(client == server::ClientType::CLIENT_WEB) + return value::TEAWEB; + + return value::QUERY; + } + }; + + PermissionNameMapper(); + virtual ~PermissionNameMapper(); + + bool initialize(const std::string& file, std::string& error); + + std::string permission_name(const Type::value& /* type */, const permission::PermissionType& /* permission */) const; + inline std::string permission_name(const server::ClientType& type, const permission::PermissionType& permission) const { + return this->permission_name(Type::from_client_type(type), permission); + } + + std::string permission_name_grant(const Type::value& /* type */, const permission::PermissionType& /* permission */) const; + inline std::string permission_name_grant(const server::ClientType& type, const permission::PermissionType& permission) const { + return this->permission_name_grant(Type::from_client_type(type), permission); + } + private: + struct PermissionMap { + std::string mapped_name; + std::string grant_name; + }; + std::array< + std::array, + Type::value::MAX + > mapping; + }; + } +} \ No newline at end of file diff --git a/shared b/shared index c8cae59..a086dcc 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit c8cae593a016b842031b5f73e103554a4f87cb66 +Subproject commit a086dcc214fe4ea7a983fecebb93b8e2fe3258ff