Commit ec68a400 authored by Jan Köster's avatar Jan Köster
Browse files

test

parent 73832c9f
Loading
Loading
Loading
Loading
+15 −14
Changes for editor/src/webedit_api.cpp: 15 added lines, 14 removed lines.
Original line number Diff line number Diff line
@@ -3720,9 +3720,9 @@ void webedit::Api::handleConnectionPublish(libhttppp::HttpRequest &curreq,

void webedit::Api::handleListConnections(libhttppp::HttpRequest &curreq,
                                          const std::string &sessionid) {
    std::string uid;
    _session.getData(sessionid, "uid", uid);
    std::string jsonStr = _db.listConnections(uid);
    std::string domain;
    _session.getData(sessionid, "domain", domain);
    std::string jsonStr = _db.listConnections(domain);
    json_object *resp = json_object_new_object();
    json_object *arr = json_tokener_parse(jsonStr.c_str());
    json_object_object_add(resp, "connections", arr ? arr : json_object_new_array());
@@ -3732,8 +3732,9 @@ void webedit::Api::handleListConnections(libhttppp::HttpRequest &curreq,

void webedit::Api::handleSaveConnection(libhttppp::HttpRequest &curreq,
                                         const std::string &sessionid) {
    std::string uid;
    std::string uid, domain;
    _session.getData(sessionid, "uid", uid);
    _session.getData(sessionid, "domain", domain);

    std::string body = getRequestBody(curreq);
    json_object *req = json_tokener_parse(body.c_str());
@@ -3764,9 +3765,9 @@ void webedit::Api::handleSaveConnection(libhttppp::HttpRequest &curreq,
    std::string connId;
    if (idObj && strlen(json_object_get_string(idObj)) > 0) {
        connId = json_object_get_string(idObj);
        _db.updateConnection(uid, connId, name, group, url, ignoreSsl);
        _db.updateConnection(domain, connId, name, group, url, ignoreSsl);
    } else {
        connId = _db.saveConnection(uid, name, group, url, ignoreSsl);
        connId = _db.saveConnection(uid, domain, name, group, url, ignoreSsl);
    }

    json_object *resp = json_object_new_object();
@@ -3780,9 +3781,9 @@ void webedit::Api::handleSaveConnection(libhttppp::HttpRequest &curreq,
void webedit::Api::handleDeleteConnection(libhttppp::HttpRequest &curreq,
                                           const std::string &sessionid,
                                           const std::string &connId) {
    std::string uid;
    _session.getData(sessionid, "uid", uid);
    _db.deleteConnection(uid, connId);
    std::string domain;
    _session.getData(sessionid, "domain", domain);
    _db.deleteConnection(domain, connId);
    json_object *resp = json_object_new_object();
    json_object_object_add(resp, "status", json_object_new_string("ok"));
    sendJson(curreq, resp);
@@ -3892,12 +3893,12 @@ json_object *webedit::Api::blogApiCall(const std::string &blogUrl, json_object *
void webedit::Api::handleConnectToConnection(libhttppp::HttpRequest &curreq,
                                              const std::string &sessionid,
                                              const std::string &connId) {
    std::string uid;
    _session.getData(sessionid, "uid", uid);
    std::string domain;
    _session.getData(sessionid, "domain", domain);
    std::string authid;
    _session.getData(sessionid, "authid", authid);

    auto result = connectToConnectionCore(uid, authid, connId);
    auto result = connectToConnectionCore(domain, authid, connId);
    if (!result.ok) {
        if (result.targets) json_object_put(result.targets);
        sendJsonError(curreq, result.httpStatus, result.error);
@@ -3917,12 +3918,12 @@ void webedit::Api::handleConnectToConnection(libhttppp::HttpRequest &curreq,
// Shared by handleConnectToConnection and mcpListPublishTargets/mcpPublishToConnection.
// On success, result.targets is a new reference the caller must json_object_put.
webedit::Api::ConnectCoreResult webedit::Api::connectToConnectionCore(
        const std::string &ownerUid, const std::string &authid, const std::string &connId) {
        const std::string &domain, const std::string &authid, const std::string &connId) {
    ConnectCoreResult result;

    std::string name, group, blogUrl;
    bool ignoreSsl = false;
    if (!_db.getConnection(ownerUid, connId, name, group, blogUrl, ignoreSsl)) {
    if (!_db.getConnection(domain, connId, name, group, blogUrl, ignoreSsl)) {
        result.httpStatus = 404;
        result.error = "Connection not found";
        return result;
+6 −6
Changes for editor/src/webedit_api.h: 6 added lines, 6 removed lines.
Original line number Diff line number Diff line
@@ -96,12 +96,12 @@ namespace webedit {
        json_object *mcpExportHtml(const std::string &domain, const std::string &docId);
        json_object *mcpImportHtml(const std::string &domain, const std::string &docId,
                                   const std::string &html);
        json_object *mcpListConnections(const std::string &ownerUid);
        json_object *mcpListPublishTargets(const std::string &ownerUid, const std::string &authid,
        json_object *mcpListConnections(const std::string &domain);
        json_object *mcpListPublishTargets(const std::string &domain, const std::string &authid,
                                           const std::string &connId);
        json_object *mcpPublishToConnection(const std::string &ownerUid, const std::string &authid,
                                            const std::string &domain, const std::string &docId,
                                            const std::string &connId, const std::string &target);
        json_object *mcpPublishToConnection(const std::string &authid, const std::string &domain,
                                            const std::string &docId, const std::string &connId,
                                            const std::string &target);

        // MCP API token management — browser-session (cookie) authenticated,
        // used from the editor's Settings UI to issue/revoke tokens for /mcp.
@@ -318,7 +318,7 @@ namespace webedit {
            std::string blogUrl;
            json_object *targets = nullptr; // caller must json_object_put(targets) if non-null
        };
        ConnectCoreResult connectToConnectionCore(const std::string &ownerUid,
        ConnectCoreResult connectToConnectionCore(const std::string &domain,
                                                  const std::string &authid,
                                                  const std::string &connId);

+52 −18
Changes for editor/src/webedit_db.cpp: 52 added lines, 18 removed lines.
Original line number Diff line number Diff line
@@ -152,6 +152,7 @@ void webedit::Database::initTables() {
    sql << "CREATE TABLE IF NOT EXISTS connections("
        <<   "id " << uuidType << ","
        <<   "owner_uid varchar(255) NOT NULL,"
        <<   "domain varchar(255) NOT NULL DEFAULT '',"
        <<   "name varchar(255) NOT NULL,"
        <<   "group_name varchar(255) DEFAULT '',"
        <<   "url " << longTextType << " NOT NULL,"
@@ -239,8 +240,39 @@ void webedit::Database::initTables() {
    tryAlter("ALTER TABLE documents ADD COLUMN domain varchar(255) NOT NULL DEFAULT ''");
    tryAlter("ALTER TABLE connections ADD COLUMN group_name varchar(255) DEFAULT ''");
    tryAlter("ALTER TABLE connections ADD COLUMN ignore_ssl integer DEFAULT 0");
    tryAlter("ALTER TABLE connections ADD COLUMN domain varchar(255) NOT NULL DEFAULT ''");
    tryAlter("ALTER TABLE document_revisions ADD COLUMN author varchar(255) DEFAULT ''");
    tryAlter("ALTER TABLE survey_templates ADD COLUMN domain varchar(255) NOT NULL DEFAULT ''");

    // One-time backfill: connections created before the domain column existed have
    // domain='' from the ALTER above. Look up each owner's domain from documents/
    // api_tokens (both already snapshot domain per owner_uid) so their existing
    // projects stay visible once connections is scoped by domain instead of owner_uid.
    auto tryExec = [&](const std::string &stmt) {
        try {
            sql.clear(); res.clear();
            sql << stmt;
            _db->exec(sql, res);
        } catch (...) {}
    };

    tryExec(
        "UPDATE connections SET domain = ("
        "SELECT domain FROM documents WHERE documents.owner_uid = connections.owner_uid "
        "AND documents.domain <> '' LIMIT 1"
        ") WHERE connections.domain = '' AND EXISTS ("
        "SELECT 1 FROM documents WHERE documents.owner_uid = connections.owner_uid "
        "AND documents.domain <> ''"
        ");");

    tryExec(
        "UPDATE connections SET domain = ("
        "SELECT domain FROM api_tokens WHERE api_tokens.owner_uid = connections.owner_uid "
        "AND api_tokens.domain <> '' LIMIT 1"
        ") WHERE connections.domain = '' AND EXISTS ("
        "SELECT 1 FROM api_tokens WHERE api_tokens.owner_uid = connections.owner_uid "
        "AND api_tokens.domain <> ''"
        ");");
}

std::string webedit::Database::getOption(const std::string &key,
@@ -563,6 +595,7 @@ bool webedit::Database::restoreRevision(const std::string &domain,
// --- Connection manager ---

std::string webedit::Database::saveConnection(const std::string &ownerUid,
                                               const std::string &domain,
                                               const std::string &name,
                                               const std::string &groupName,
                                               const std::string &url,
@@ -572,11 +605,12 @@ std::string webedit::Database::saveConnection(const std::string &ownerUid,

    dbpp::SQL sql;
    dbpp::DBResult res;
    std::vector<char> eOwner, eName, eGroup, eUrl;
    std::vector<char> eOwner, eDomain, eName, eGroup, eUrl;

    sql << "INSERT INTO connections (id, owner_uid, name, group_name, url, ignore_ssl) VALUES ('"
    sql << "INSERT INTO connections (id, owner_uid, domain, name, group_name, url, ignore_ssl) VALUES ('"
        << connId.c_str() << "','"
        << dbpp::SQL::escaped(eOwner, ownerUid.c_str()) << "','"
        << dbpp::SQL::escaped(eDomain, domain.c_str()) << "','"
        << dbpp::SQL::escaped(eName, name.c_str()) << "','"
        << dbpp::SQL::escaped(eGroup, groupName.c_str()) << "','"
        << dbpp::SQL::escaped(eUrl, url.c_str()) << "',"
@@ -586,7 +620,7 @@ std::string webedit::Database::saveConnection(const std::string &ownerUid,
    return connId.c_str();
}

std::string webedit::Database::updateConnection(const std::string &ownerUid,
std::string webedit::Database::updateConnection(const std::string &domain,
                                                 const std::string &id,
                                                 const std::string &name,
                                                 const std::string &groupName,
@@ -594,42 +628,42 @@ std::string webedit::Database::updateConnection(const std::string &ownerUid,
                                                 bool ignoreSsl) {
    dbpp::SQL sql;
    dbpp::DBResult res;
    std::vector<char> eId, eOwner, eName, eGroup, eUrl;
    std::vector<char> eId, eDomain, eName, eGroup, eUrl;

    sql << "UPDATE connections SET name='"
        << dbpp::SQL::escaped(eName, name.c_str()) << "', group_name='"
        << dbpp::SQL::escaped(eGroup, groupName.c_str()) << "', url='"
        << dbpp::SQL::escaped(eUrl, url.c_str()) << "', ignore_ssl="
        << (ignoreSsl ? 1 : 0) << " WHERE id='"
        << dbpp::SQL::escaped(eId, id.c_str()) << "' AND owner_uid='"
        << dbpp::SQL::escaped(eOwner, ownerUid.c_str()) << "';";
        << dbpp::SQL::escaped(eId, id.c_str()) << "' AND domain='"
        << dbpp::SQL::escaped(eDomain, domain.c_str()) << "';";

    _db->exec(sql, res);
    return id;
}

bool webedit::Database::deleteConnection(const std::string &ownerUid,
bool webedit::Database::deleteConnection(const std::string &domain,
                                          const std::string &id) {
    dbpp::SQL sql;
    dbpp::DBResult res;
    std::vector<char> eId, eOwner;
    std::vector<char> eId, eDomain;

    sql << "DELETE FROM connections WHERE id='"
        << dbpp::SQL::escaped(eId, id.c_str()) << "' AND owner_uid='"
        << dbpp::SQL::escaped(eOwner, ownerUid.c_str()) << "';";
        << dbpp::SQL::escaped(eId, id.c_str()) << "' AND domain='"
        << dbpp::SQL::escaped(eDomain, domain.c_str()) << "';";

    _db->exec(sql, res);
    return true;
}

std::string webedit::Database::listConnections(const std::string &ownerUid) {
std::string webedit::Database::listConnections(const std::string &domain) {
    dbpp::SQL sql;
    dbpp::DBResult res;
    std::vector<char> eOwner;
    std::vector<char> eDomain;

    sql << "SELECT id, name, group_name, url, ignore_ssl, created "
        << "FROM connections WHERE owner_uid='"
        << dbpp::SQL::escaped(eOwner, ownerUid.c_str())
        << "FROM connections WHERE domain='"
        << dbpp::SQL::escaped(eDomain, domain.c_str())
        << "' ORDER BY group_name, name;";

    int rows = _db->exec(sql, res);
@@ -652,17 +686,17 @@ std::string webedit::Database::listConnections(const std::string &ownerUid) {
    return result;
}

bool webedit::Database::getConnection(const std::string &ownerUid,
bool webedit::Database::getConnection(const std::string &domain,
                                       const std::string &id, std::string &name,
                                       std::string &groupName, std::string &url,
                                       bool &ignoreSsl) {
    dbpp::SQL sql;
    dbpp::DBResult res;
    std::vector<char> eId, eOwner;
    std::vector<char> eId, eDomain;

    sql << "SELECT name, group_name, url, ignore_ssl FROM connections WHERE id='"
        << dbpp::SQL::escaped(eId, id.c_str()) << "' AND owner_uid='"
        << dbpp::SQL::escaped(eOwner, ownerUid.c_str()) << "';";
        << dbpp::SQL::escaped(eId, id.c_str()) << "' AND domain='"
        << dbpp::SQL::escaped(eDomain, domain.c_str()) << "';";

    int rows = _db->exec(sql, res);
    if (rows < 1) return false;
+9 −8
Changes for editor/src/webedit_db.h: 9 added lines, 8 removed lines.
Original line number Diff line number Diff line
@@ -68,16 +68,17 @@ namespace webedit {
        std::string getOption(const std::string &key, const std::string &defaultVal = "");
        void setOption(const std::string &key, const std::string &value);

        // Connection manager (per-user)
        std::string saveConnection(const std::string &ownerUid, const std::string &name,
                                   const std::string &groupName, const std::string &url,
                                   bool ignoreSsl);
        std::string updateConnection(const std::string &ownerUid, const std::string &id,
        // Connection manager ("projects" in the UI) — visible/editable by every
        // user of the same domain (same pattern as documents/surveys above).
        std::string saveConnection(const std::string &ownerUid, const std::string &domain,
                                   const std::string &name, const std::string &groupName,
                                   const std::string &url, bool ignoreSsl);
        bool deleteConnection(const std::string &ownerUid, const std::string &id);
        std::string listConnections(const std::string &ownerUid);
        bool getConnection(const std::string &ownerUid, const std::string &id,
        std::string updateConnection(const std::string &domain, const std::string &id,
                                     const std::string &name, const std::string &groupName,
                                     const std::string &url, bool ignoreSsl);
        bool deleteConnection(const std::string &domain, const std::string &id);
        std::string listConnections(const std::string &domain);
        bool getConnection(const std::string &domain, const std::string &id,
                           std::string &name, std::string &groupName,
                           std::string &url, bool &ignoreSsl);