Finishing up backbone

Latest advances to unify the underlying server mechanics and processes proved to be successful, as of right now we have developed tools and scripts to migrate over the last culprit: permissions.

Computer servers

Basically permissions are currently being handled by Privileges, a very robust and highly efficient permission handler. However, due to its barebone nature, development is really slow when new advances are being introduced (for example uuids or mysql database support). I’ve opted to move to PermissionsEx. In the past I had a love/hate relationship with this manager, as it had some major flaws. Judging from their development releases, they seem to have fixed all those longstanding issues. Really well done!

PermissionsEx adds a whole load of functionality compared to Privileges, mainly:

  • Support for UUID
  • MySQL backend support
  • Has an API
  • Multigroup Inheritance
  • Low-level caching to increase performance
  • Timed permissions
  • SuperPerms format compatible

However switching from one to the other isn’t simple. Both managers use a different YAML format, and editing over 400.000 entries by hand would literally take months and eat away all the sanity left within me. A fix was needed in order to convert the Privileges YAML to the PermissionsEx YAML layout.

There is a YAML parser available on Google Code, called yaml-cpp. Available here: https://code.google.com/p/yaml-cpp/

Using the following code, let’s call the file main.cpp for this purpose.

#include <yaml-cpp/yaml.h>
#include <iostream>
#include <fstream>
#include <vector>

int main(int argc, char * argv[]) {
    if(argc != 3) {
        std::cout << "[!] Usage: " << argv[0] << " <input file> <output file>"
            << std::endl;
        return -1;
    }
    YAML::Node config;
    try {
        config = YAML::LoadFile(argv[1]);
    } catch(YAML::BadFile e) {
        std::cout << "[!] File " << argv[1]
            << " does not exist or is not proper YAML file." << std::endl;
        return -1;
    }
    std::ofstream out(argv[2]);
    if(!out.is_open()) {
        std::cout << "[!] Unable to open file: " << argv[2] << std::endl;
    }
    std::vector<std::string> rm;
    std::cout << "[A] Parsing config..." << std::endl;
    YAML::Node users = config["users"];
    for(YAML::const_iterator it = users.begin(); it != users.end(); ++it) {
        if(it->second["group"].as<std::string>() == "adventurer") {
            rm.push_back(it->first.as<std::string>());
        }
    }
    std::cout << "[+] Parsed." << std::endl;
    std::cout << "[A] Removing unnecessary nodes..." << std::endl;
    for(int i=0; i<rm.size(); ++i) {
        config["users"].remove(rm[i]);
    }
    std::cout << "[+] Removed." << std::endl;
    out << config;
    out.close();
    std::cout << "[+] Saved file " << argv[2] << std::endl;
    return 0;
}

Compiling the code is done by issuing:

g++ main.cpp -o main -lyaml-cpp

Afterwards files can be converted by issuing:

./main config.yml output.yml

I will find the time somewhere in this week to continue working on it. I will have to check out if all the groups inherit their permissions correctly on my test server before this gets deployed.

Leave a Reply