#include #include #include #include #include #include "InstanceHandler.h" #include "src/client/InternalClient.h" #include "src/server/QueryServer.h" #include "src/server/file/LocalFileServer.h" using namespace std; using namespace std::chrono; using namespace ts; using namespace ts::server; #define TEST_COMMENT if(line.find('#') == 0 || line.empty()) continue #define PERMISSION_TEMPLATE_FILE "resources/permissions.template" struct GroupInfo { /** * 0 = Query * 1 = Server * 2 = Channel */ int target; std::deque properties; string name; /* permission type, value, granted, skip, negate */ deque> permissions; }; /* TODO may use a transaction here? */ bool InstanceHandler::setupDefaultGroups() { debugMessage(LOG_INSTANCE, "Creating new instance groups"); deque> groups; ifstream in(PERMISSION_TEMPLATE_FILE); if(!in) { logCritical(LOG_INSTANCE, "Could not open default permissions file {}", PERMISSION_TEMPLATE_FILE); return false; } string line; while(getline(in, line)){ TEST_COMMENT; if(line != "--start") { logCritical(LOG_INSTANCE, R"(Permission template file contains invalid start line ("{}", expected "{}")!)", line, "--start"); return false; } auto group = make_shared(); while(true){ getline(in, line); TEST_COMMENT; if(line == "--end") break; if(line.find("name:") == 0) { group->name = line.substr(5); continue; } if(line.find("target:") == 0) { group->target = stoi(line.substr(7)); continue; } if(line.find("property:") == 0) { group->properties.push_back(line.substr(9)); continue; } if(line.find("permission:") == 0) { line = line.substr(11); auto assign_index = line.find('='); string permission_name = line.substr(0, assign_index); string string_value = line.substr(assign_index + 1); string string_granted, string_skip, string_negate; if(string_value.find(',') != -1) { string_granted = string_value.substr(string_value.find(',') + 1); string_value = string_value.substr(0, string_value.find(',')); } if(string_granted.find(',') != -1) { string_skip = string_granted.substr(string_granted.find(',') + 1); string_granted = string_granted.substr(0, string_granted.find(',')); } if(string_skip.find(',') != -1) { string_negate = string_skip.substr(string_skip.find(',') + 1); string_skip = string_skip.substr(0, string_skip.find(',')); } auto permInfo = permission::resolvePermissionData(permission_name); if(permInfo->type == permission::unknown){ logError(LOG_INSTANCE, "Default permission file contains unknown permission. Key: {}", permission_name); continue; } permission::PermissionValue permission_value; try { permission_value = stoi(string_value); } catch(std::exception& ex) { logError(LOG_INSTANCE, "Failed to parse value for key {}. Value: {}", permission_name, string_value); continue; } permission::PermissionValue permission_granted = permNotGranted; if(!string_granted.empty()) { try { permission_granted = stoi(string_granted); } catch(std::exception& ex) { logError(LOG_INSTANCE, "Failed to parse granted value for key {}. Value: {}", permission_name, string_granted); continue; } } bool flag_skip = string_skip == "true" || string_skip == "1"; bool flag_negate = string_negate == "true" || string_negate == "1"; group->permissions.emplace_back(make_tuple(permInfo->type, permission_value, permission_granted, flag_skip, flag_negate)); } } groups.push_back(group); } debugMessage(LOG_INSTANCE, "Read " + to_string(groups.size()) + " default groups"); for(const auto& info : groups) { debugMessage(LOG_INSTANCE, "Creating default group {} with type {}", info->name, to_string(info->target)); //Query groups auto group = this->groupManager->createGroup( info->target != 2 ? GroupTarget::GROUPTARGET_SERVER : GroupTarget::GROUPTARGET_CHANNEL, info->target == 0 ? GroupType::GROUP_TYPE_QUERY : GroupType::GROUP_TYPE_TEMPLATE, info->name ); for(auto perm : info->permissions) { group->permissions()->set_permission(get<0>(perm), {get<1>(perm), get<2>(perm)}, permission::v2::set_value, permission::v2::set_value, get<3>(perm), get<4>(perm)); } for(const auto& property : info->properties) { const auto& prop = property::find(property); if(prop.is_undefined()) { logCritical(LOG_INSTANCE, "Invalid template property name: " + property); } else { this->properties()[prop] = group->groupId(); } } } this->save_group_permissions(); this->getSql()->pool->threads()->wait_for(); //Wait for all permissions to flush return true; }