Loading src/admin.cpp +39 −6 Original line number Diff line number Diff line Loading @@ -1898,9 +1898,25 @@ namespace authdb { if (ctHdr && ctHdr->getfirstValue()) { std::string ct = ctHdr->getfirstValue()->getvalue(); if (ct.find("application/json") != std::string::npos) { ::uuid::uuid adminDid; // Extract domain from URL: /settings/{domain}/api ::uuid::uuid domainDid; const std::string &reqUrl = curreq.getRequestURL(); char domBuf[255] = {}; if (sscanf(reqUrl.c_str(), "/settings/%[^/]/api", domBuf) == 1 && strcmp(domBuf, "admin") != 0) { // Try parsing as UUID first, fall back to name lookup domainDid = ::uuid::uuid(domBuf); if (domainDid.empty()) { AuthBackend::Guard guard(_AdminBackend, AuthBackend::Shared); RecordIndex &idx = _AdminBackend.getIndex(); if (!idx.valid() || idx.revision() != _AdminBackend.getRevesion()) idx.build(_AdminBackend); idx.findByName(DataType::DomainData, "domainname", std::string(domBuf), domainDid); } } AuthBackend::Guard guard(_AdminBackend, AuthBackend::Shared); ApiController(_AdminBackend, adminDid, curreq, tid, args); ApiController(_AdminBackend, domainDid, curreq, tid, args); return; } } Loading Loading @@ -2038,11 +2054,17 @@ namespace authdb { return; } // JSON command API at /settings/admin/api (client library protocol) // JSON command API at /settings/{domain}/api (client library protocol) // This endpoint handles its own auth (ClientAuth/UserAuth in JSON body) { const std::string &reqUrl = curreq.getRequestURL(); if (reqUrl == "/settings/admin/api" || reqUrl == "/settings/admin/api/") { char domBuf[255] = {}; bool isApiPath = (reqUrl == "/settings/admin/api" || reqUrl == "/settings/admin/api/"); if (!isApiPath) { // Match /settings/{domain}/api or /settings/{domain}/api/ isApiPath = (sscanf(reqUrl.c_str(), "/settings/%[^/]/api", domBuf) == 1); } if (isApiPath) { libhttppp::HttpHeader::HeaderData *ct = nullptr; try { ct = curreq.getHeaderData("content-type"); } catch(...) {} bool isJson = false; Loading @@ -2052,9 +2074,20 @@ namespace authdb { } if (isJson) { try { ::uuid::uuid adminDid; ::uuid::uuid domainDid; if (domBuf[0] && strcmp(domBuf, "admin") != 0) { // Try parsing as UUID first, fall back to name lookup domainDid = ::uuid::uuid(domBuf); if (domainDid.empty()) { RecordIndex &idx = _AdminBackend.getIndex(); if (!idx.valid() || idx.revision() != _AdminBackend.getRevesion()) idx.build(_AdminBackend); idx.findByName(DataType::DomainData, "domainname", std::string(domBuf), domainDid); } } AuthBackend::Guard guard(_AdminBackend, AuthBackend::Shared); ApiController(_AdminBackend, adminDid, curreq, tid, args); ApiController(_AdminBackend, domainDid, curreq, tid, args); } catch (AuthBackendError &e) { json_object *jerr = json_object_new_array(); json_object *eobj = json_object_new_object(); Loading src/api.cpp +30 −0 Original line number Diff line number Diff line Loading @@ -296,6 +296,36 @@ public: user.info(_Backend, *udat, upos); if (constant_time_eq(pwsalt, udat->getPwHash())) { // If no domain specified (admin path), restrict to SuperAdmins // and assign them to the "admin.local" domain if (_Did.empty()) { // Check SuperAdmin group membership Group group; std::vector<uuid::uuid> gids; group.list(_Backend, gids); bool isSuperAdmin = false; for (auto &gid : gids) { std::shared_ptr<GroupData> grpi = std::make_shared<GroupData>(gid); size_t gpos = sizeof(AuthHeader); group.info(_Backend, *grpi, gpos); if (grpi->getName() == "SuperAdmin" && grpi->isMember(found_uid)) { isSuperAdmin = true; break; } } if (!isSuperAdmin) return nullptr; // not a SuperAdmin // Resolve "admin.local" domain RecordIndex &didx = _Backend.getIndex(); if (!didx.valid() || didx.revision() != _Backend.getRevesion()) didx.build(_Backend); didx.findByName(DataType::DomainData, "domainname", std::string("admin.local"), _Did); } const SessionData* sdat = AuthSession->addSession(_Backend, _Did.value, found_uid.value); Loading Loading
src/admin.cpp +39 −6 Original line number Diff line number Diff line Loading @@ -1898,9 +1898,25 @@ namespace authdb { if (ctHdr && ctHdr->getfirstValue()) { std::string ct = ctHdr->getfirstValue()->getvalue(); if (ct.find("application/json") != std::string::npos) { ::uuid::uuid adminDid; // Extract domain from URL: /settings/{domain}/api ::uuid::uuid domainDid; const std::string &reqUrl = curreq.getRequestURL(); char domBuf[255] = {}; if (sscanf(reqUrl.c_str(), "/settings/%[^/]/api", domBuf) == 1 && strcmp(domBuf, "admin") != 0) { // Try parsing as UUID first, fall back to name lookup domainDid = ::uuid::uuid(domBuf); if (domainDid.empty()) { AuthBackend::Guard guard(_AdminBackend, AuthBackend::Shared); RecordIndex &idx = _AdminBackend.getIndex(); if (!idx.valid() || idx.revision() != _AdminBackend.getRevesion()) idx.build(_AdminBackend); idx.findByName(DataType::DomainData, "domainname", std::string(domBuf), domainDid); } } AuthBackend::Guard guard(_AdminBackend, AuthBackend::Shared); ApiController(_AdminBackend, adminDid, curreq, tid, args); ApiController(_AdminBackend, domainDid, curreq, tid, args); return; } } Loading Loading @@ -2038,11 +2054,17 @@ namespace authdb { return; } // JSON command API at /settings/admin/api (client library protocol) // JSON command API at /settings/{domain}/api (client library protocol) // This endpoint handles its own auth (ClientAuth/UserAuth in JSON body) { const std::string &reqUrl = curreq.getRequestURL(); if (reqUrl == "/settings/admin/api" || reqUrl == "/settings/admin/api/") { char domBuf[255] = {}; bool isApiPath = (reqUrl == "/settings/admin/api" || reqUrl == "/settings/admin/api/"); if (!isApiPath) { // Match /settings/{domain}/api or /settings/{domain}/api/ isApiPath = (sscanf(reqUrl.c_str(), "/settings/%[^/]/api", domBuf) == 1); } if (isApiPath) { libhttppp::HttpHeader::HeaderData *ct = nullptr; try { ct = curreq.getHeaderData("content-type"); } catch(...) {} bool isJson = false; Loading @@ -2052,9 +2074,20 @@ namespace authdb { } if (isJson) { try { ::uuid::uuid adminDid; ::uuid::uuid domainDid; if (domBuf[0] && strcmp(domBuf, "admin") != 0) { // Try parsing as UUID first, fall back to name lookup domainDid = ::uuid::uuid(domBuf); if (domainDid.empty()) { RecordIndex &idx = _AdminBackend.getIndex(); if (!idx.valid() || idx.revision() != _AdminBackend.getRevesion()) idx.build(_AdminBackend); idx.findByName(DataType::DomainData, "domainname", std::string(domBuf), domainDid); } } AuthBackend::Guard guard(_AdminBackend, AuthBackend::Shared); ApiController(_AdminBackend, adminDid, curreq, tid, args); ApiController(_AdminBackend, domainDid, curreq, tid, args); } catch (AuthBackendError &e) { json_object *jerr = json_object_new_array(); json_object *eobj = json_object_new_object(); Loading
src/api.cpp +30 −0 Original line number Diff line number Diff line Loading @@ -296,6 +296,36 @@ public: user.info(_Backend, *udat, upos); if (constant_time_eq(pwsalt, udat->getPwHash())) { // If no domain specified (admin path), restrict to SuperAdmins // and assign them to the "admin.local" domain if (_Did.empty()) { // Check SuperAdmin group membership Group group; std::vector<uuid::uuid> gids; group.list(_Backend, gids); bool isSuperAdmin = false; for (auto &gid : gids) { std::shared_ptr<GroupData> grpi = std::make_shared<GroupData>(gid); size_t gpos = sizeof(AuthHeader); group.info(_Backend, *grpi, gpos); if (grpi->getName() == "SuperAdmin" && grpi->isMember(found_uid)) { isSuperAdmin = true; break; } } if (!isSuperAdmin) return nullptr; // not a SuperAdmin // Resolve "admin.local" domain RecordIndex &didx = _Backend.getIndex(); if (!didx.valid() || didx.revision() != _Backend.getRevesion()) didx.build(_Backend); didx.findByName(DataType::DomainData, "domainname", std::string("admin.local"), _Did); } const SessionData* sdat = AuthSession->addSession(_Backend, _Did.value, found_uid.value); Loading