Commit 7064c002 authored by jan.koester's avatar jan.koester
Browse files

test

parent e0cd5e0e
Loading
Loading
Loading
Loading
Loading
+239 −0
Changes for src/admin.cpp: 239 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -144,6 +144,35 @@ namespace fenrirds {

        /* ---- JSON API: List Users ---- */
        void apiListUsers(libhttppp::HttpRequest &curreq, const char *cdid) {
            /* the admin console (admin.local) has no directory — its own
             * accounts (SuperAdmins) are native; list them from the backend */
            if (strcmp(cdid, "admin") == 0) {
                json_object *jobj = json_object_new_object();
                json_object *jarr = json_object_new_array();
                User user;
                std::vector<uuid::uuid> uuids;
                user.list(_AdminBackend, uuids);
                for (const auto &uid : uuids) {
                    class UserData udat(uid);
                    try {
                        size_t upos = sizeof(fenrirds::AuthHeader);
                        user.info(_AdminBackend, udat, upos);
                        json_object *juser = json_object_new_object();
                        json_object_object_add(juser, "uid", json_object_new_string(uid.c_str()));
                        json_object_object_add(juser, "username", json_object_new_string(udat.getUsername().c_str()));
                        try { json_object_object_add(juser, "firstname", json_object_new_string(udat.getFirstname().c_str())); } catch (...) {}
                        try { json_object_object_add(juser, "lastname", json_object_new_string(udat.getLastname().c_str())); } catch (...) {}
                        try { json_object_object_add(juser, "mail", json_object_new_string(udat.getMail().c_str())); } catch (...) {}
                        json_object_object_add(juser, "windowslogin", json_object_new_boolean(false));
                        json_object_array_add(jarr, juser);
                    } catch (AuthBackendError &e) { std::cerr << e.what() << std::endl; }
                }
                json_object_object_add(jobj, "users", jarr);
                sendJson(curreq, jobj);
                json_object_put(jobj);
                return;
            }

            std::string domain = domainNameFor(cdid);
            if (domain.empty() || !g_AdPlugin)
                throw AuthBackendError("listUsers: no directory for domain!");
@@ -174,6 +203,32 @@ namespace fenrirds {

        /* ---- JSON API: Get User (for edit form) ---- */
        void apiGetUser(libhttppp::HttpRequest &curreq, const char *cdid, const char *cuid) {
            if (strcmp(cdid, "admin") == 0) {
                /* admin console: native SuperAdmin account */
                uuid::uuid uid; uid.parse(cuid);
                User user;
                class UserData udat(uid);
                size_t upos = sizeof(AuthHeader);
                user.info(_AdminBackend, udat, upos);
                json_object *jobj = json_object_new_object();
                json_object *jfields = json_object_new_array();
                auto af = [&](const char *name, const std::string &val) {
                    json_object *jf = json_object_new_object();
                    json_object_object_add(jf, "name", json_object_new_string(name));
                    json_object_object_add(jf, "value", json_object_new_string(val.c_str()));
                    json_object_array_add(jfields, jf);
                };
                try { af("username", udat.getUsername()); } catch (...) {}
                try { af("firstname", udat.getFirstname()); } catch (...) {}
                try { af("lastname", udat.getLastname()); } catch (...) {}
                try { af("mail", udat.getMail()); } catch (...) {}
                json_object_object_add(jobj, "fields", jfields);
                json_object_object_add(jobj, "windowslogin", json_object_new_boolean(false));
                sendJson(curreq, jobj);
                json_object_put(jobj);
                return;
            }

            std::string domain = domainNameFor(cdid);
            if (domain.empty() || !g_AdPlugin)
                throw AuthBackendError("getUser: no directory for domain!");
@@ -210,6 +265,46 @@ namespace fenrirds {

        /* ---- JSON API: Create User (directory object) ---- */
        void apiCreateUser(libhttppp::HttpRequest &curreq, const char *cdid) {
            if (strcmp(cdid, "admin") == 0) {
                /* admin console: create a native SuperAdmin account */
                libhttppp::HttpForm curform; curform.parse(curreq);
                uuid::uuid uid; uid.generate();
                class UserData udat(uid);
                std::string uname, pw;
                for (const auto &fd : curform.multipartData()) {
                    if (fd.value.empty()) continue;
                    std::string name;
                    for (const auto &d : fd.dispositions) {
                        std::string k = d.key;
                        std::transform(k.begin(), k.end(), k.begin(), [](unsigned char c){ return std::tolower(c); });
                        if (k == "name") name = d.value;
                    }
                    std::string val(fd.value.begin(), fd.value.end());
                    if (name == "username")       { uname = val; udat.setUserName(val); }
                    else if (name == "firstname") udat.setFirstName(val);
                    else if (name == "lastname")  udat.setLastName(val);
                    else if (name == "mail")      udat.setMail(val);
                    else if (name == "pwhash")    pw = val;
                }
                if (uname.empty()) throw AuthBackendError("username not set!");
                if (!pw.empty()) { Hash h; std::string hh; h.hash(pw, hh); udat.setPwHash(hh); }
                User user;
                user.create(_AdminBackend, &udat);
                /* add to the native SuperAdmin group so it has admin rights */
                Group group; std::vector<uuid::uuid> gids; group.list(_AdminBackend, gids);
                for (const auto &gid : gids) {
                    class GroupData gd(gid); size_t gp = sizeof(AuthHeader);
                    try { group.info(_AdminBackend, gd, gp); } catch (...) { continue; }
                    if (gd.getName() == "SuperAdmin") { gd.addMember(uid); gp = sizeof(AuthHeader); group.edit(_AdminBackend, gd, gp); break; }
                }
                json_object *jobj = json_object_new_object();
                json_object_object_add(jobj, "status", json_object_new_string("ok"));
                json_object_object_add(jobj, "uid", json_object_new_string(uid.c_str()));
                sendJson(curreq, jobj);
                json_object_put(jobj);
                return;
            }

            std::string domain = domainNameFor(cdid);
            if (domain.empty() || !g_AdPlugin)
                throw AuthBackendError("createUser: no directory for domain!");
@@ -282,6 +377,16 @@ namespace fenrirds {

        /* ---- JSON API: Remove User ---- */
        void apiRemoveUser(libhttppp::HttpRequest &curreq, const char *cdid, const char *cuid) {
            if (strcmp(cdid, "admin") == 0) {
                uuid::uuid uid; uid.parse(cuid);
                User user; user.remove(_AdminBackend, uid);
                json_object *jok = json_object_new_object();
                json_object_object_add(jok, "status", json_object_new_string("ok"));
                sendJson(curreq, jok);
                json_object_put(jok);
                return;
            }

            std::string domain = domainNameFor(cdid);
            if (domain.empty() || !g_AdPlugin)
                throw AuthBackendError("removeUser: no directory for domain!");
@@ -300,6 +405,35 @@ namespace fenrirds {

        /* ---- JSON API: Edit User (directory object) ---- */
        void apiEditUser(libhttppp::HttpRequest &curreq, const char *cdid, const char *cuid) {
            if (strcmp(cdid, "admin") == 0) {
                /* admin console: edit a native SuperAdmin account */
                uuid::uuid uid; uid.parse(cuid);
                libhttppp::HttpForm curform; curform.parse(curreq);
                User user; class UserData udat(uid); size_t upos = sizeof(AuthHeader);
                user.info(_AdminBackend, udat, upos);
                for (const auto &fd : curform.multipartData()) {
                    if (fd.value.empty()) continue;
                    std::string name;
                    for (const auto &d : fd.dispositions) {
                        std::string k = d.key;
                        std::transform(k.begin(), k.end(), k.begin(), [](unsigned char c){ return std::tolower(c); });
                        if (k == "name") name = d.value;
                    }
                    std::string val(fd.value.begin(), fd.value.end());
                    if (name == "firstname")      udat.setFirstName(val);
                    else if (name == "lastname")  udat.setLastName(val);
                    else if (name == "mail")      udat.setMail(val);
                    else if (name == "pwhash" && !val.empty()) { Hash h; std::string hh; h.hash(val, hh); udat.setPwHash(hh); }
                }
                upos = sizeof(AuthHeader);
                user.edit(_AdminBackend, udat, upos);
                json_object *jok = json_object_new_object();
                json_object_object_add(jok, "status", json_object_new_string("ok"));
                sendJson(curreq, jok);
                json_object_put(jok);
                return;
            }

            std::string domain = domainNameFor(cdid);
            if (domain.empty() || !g_AdPlugin)
                throw AuthBackendError("editUser: no directory for domain!");
@@ -912,6 +1046,31 @@ namespace fenrirds {

        /* ---- JSON API: List Groups ---- */
        void apiListGroups(libhttppp::HttpRequest &curreq, const char *cdid) {
            if (strcmp(cdid, "admin") == 0) {
                /* admin console: native groups (e.g. SuperAdmin) */
                json_object *jobj = json_object_new_object();
                json_object *jarr = json_object_new_array();
                Group group;
                std::vector<uuid::uuid> gids;
                group.list(_AdminBackend, gids);
                for (const auto &gid : gids) {
                    class GroupData gdat(gid);
                    try {
                        size_t gpos = sizeof(fenrirds::AuthHeader);
                        group.info(_AdminBackend, gdat, gpos);
                        json_object *jgrp = json_object_new_object();
                        json_object_object_add(jgrp, "gid", json_object_new_string(gid.c_str()));
                        json_object_object_add(jgrp, "name", json_object_new_string(gdat.getName().c_str()));
                        json_object_object_add(jgrp, "windowslogin", json_object_new_boolean(false));
                        json_object_array_add(jarr, jgrp);
                    } catch (AuthBackendError &e) { std::cerr << e.what() << std::endl; }
                }
                json_object_object_add(jobj, "groups", jarr);
                sendJson(curreq, jobj);
                json_object_put(jobj);
                return;
            }

            std::string domain = domainNameFor(cdid);
            if (domain.empty() || !g_AdPlugin)
                throw AuthBackendError("listGroups: no directory for domain!");
@@ -937,6 +1096,34 @@ namespace fenrirds {

        /* ---- JSON API: Get Group (for edit) ---- */
        void apiGetGroup(libhttppp::HttpRequest &curreq, const char *cdid, const char *cgid) {
            if (strcmp(cdid, "admin") == 0) {
                /* admin console: native group + native member picker */
                uuid::uuid gid(cgid);
                class GroupData gdat(gid); Group grp; size_t pos = sizeof(AuthHeader);
                grp.info(_AdminBackend, gdat, pos);
                json_object *jobj = json_object_new_object();
                json_object_object_add(jobj, "groupname", json_object_new_string(gdat.getName().c_str()));
                std::vector<uuid::uuid> mrecs; gdat.getMembers(mrecs);
                json_object *jmembers = json_object_new_array();
                for (const auto &m : mrecs) json_object_array_add(jmembers, json_object_new_string(m.c_str()));
                json_object_object_add(jobj, "members", jmembers);
                json_object *jall = json_object_new_array();
                User usr; std::vector<uuid::uuid> uids; usr.list(_AdminBackend, uids);
                for (const auto &uid : uids) {
                    class UserData udat(uid);
                    try { size_t up = sizeof(AuthHeader); usr.info(_AdminBackend, udat, up);
                        json_object *ju = json_object_new_object();
                        json_object_object_add(ju, "uid", json_object_new_string(uid.c_str()));
                        json_object_object_add(ju, "username", json_object_new_string(udat.getUsername().c_str()));
                        json_object_array_add(jall, ju);
                    } catch (...) {}
                }
                json_object_object_add(jobj, "allusers", jall);
                sendJson(curreq, jobj);
                json_object_put(jobj);
                return;
            }

            std::string domain = domainNameFor(cdid);
            if (domain.empty() || !g_AdPlugin)
                throw AuthBackendError("getGroup: no directory for domain!");
@@ -984,6 +1171,27 @@ namespace fenrirds {

        /* ---- JSON API: Create Group (directory object) ---- */
        void apiCreateGroup(libhttppp::HttpRequest &curreq, const char *cdid) {
            if (strcmp(cdid, "admin") == 0) {
                std::string reqbody = getRequestBody(curreq);
                json_object *jreq = json_tokener_parse(reqbody.c_str());
                if (!jreq) throw AuthBackendError("createGroup: invalid JSON!");
                json_object *jname = json_object_object_get(jreq, "groupname");
                json_object *jmembers = json_object_object_get(jreq, "groupmembers");
                uuid::uuid gid; gid.generate(); class GroupData gd(gid);
                if (jname) gd.setName(json_object_get_string(jname));
                if (jmembers && json_object_get_type(jmembers) == json_type_array)
                    for (int i = 0; i < json_object_array_length(jmembers); i++)
                        gd.addMember(uuid::uuid(json_object_get_string(json_object_array_get_idx(jmembers, i))));
                Group grp; grp.create(_AdminBackend, &gd);
                json_object_put(jreq);
                json_object *jobj = json_object_new_object();
                json_object_object_add(jobj, "status", json_object_new_string("ok"));
                json_object_object_add(jobj, "gid", json_object_new_string(gid.c_str()));
                sendJson(curreq, jobj);
                json_object_put(jobj);
                return;
            }

            std::string domain = domainNameFor(cdid);
            if (domain.empty() || !g_AdPlugin)
                throw AuthBackendError("createGroup: no directory for domain!");
@@ -1029,6 +1237,16 @@ namespace fenrirds {

        /* ---- JSON API: Remove Group ---- */
        void apiRemoveGroup(libhttppp::HttpRequest &curreq, const char *cdid, const char *cgid) {
            if (strcmp(cdid, "admin") == 0) {
                uuid::uuid gid; gid.parse(cgid);
                Group group; group.remove(_AdminBackend, gid);
                json_object *jok = json_object_new_object();
                json_object_object_add(jok, "status", json_object_new_string("ok"));
                sendJson(curreq, jok);
                json_object_put(jok);
                return;
            }

            std::string domain = domainNameFor(cdid);
            if (domain.empty() || !g_AdPlugin)
                throw AuthBackendError("removeGroup: no directory for domain!");
@@ -1047,6 +1265,27 @@ namespace fenrirds {

        /* ---- JSON API: Edit Group (reconcile membership) ---- */
        void apiEditGroup(libhttppp::HttpRequest &curreq, const char *cdid, const char *cgid) {
            if (strcmp(cdid, "admin") == 0) {
                uuid::uuid gid(cgid);
                std::string reqbody = getRequestBody(curreq);
                json_object *jreq = json_tokener_parse(reqbody.c_str());
                if (!jreq) throw AuthBackendError("editGroup: invalid JSON!");
                json_object *jname = json_object_object_get(jreq, "groupname");
                json_object *jmem = json_object_object_get(jreq, "groupmembers");
                class GroupData editrec(gid);
                if (jname) editrec.setName(json_object_get_string(jname));
                if (jmem && json_object_get_type(jmem) == json_type_array)
                    for (int i = 0; i < json_object_array_length(jmem); i++)
                        editrec.addMember(uuid::uuid(json_object_get_string(json_object_array_get_idx(jmem, i))));
                Group grp; size_t pos = sizeof(AuthHeader); grp.edit(_AdminBackend, editrec, pos);
                json_object_put(jreq);
                json_object *jok = json_object_new_object();
                json_object_object_add(jok, "status", json_object_new_string("ok"));
                sendJson(curreq, jok);
                json_object_put(jok);
                return;
            }

            std::string domain = domainNameFor(cdid);
            if (domain.empty() || !g_AdPlugin)
                throw AuthBackendError("editGroup: no directory for domain!");