Loading editor/html/css/editor.css +5 −5 Changes for editor/html/css/editor.css: 5 added lines, 5 removed lines. Original line number Diff line number Diff line Loading @@ -1403,16 +1403,16 @@ dialog label { ============================================================ */ .survey-manager-dialog { width: min(92vw, 960px); max-height: 90vh; width: min(96vw, 1400px); max-height: 92vh; } .survey-manager-dialog .set-modal { min-height: 480px; min-height: 700px; } .sm-survey-list { max-height: 300px; max-height: 520px; overflow-y: auto; } Loading Loading @@ -1444,7 +1444,7 @@ dialog label { .sm-editor-layout { display: grid; grid-template-columns: 1fr 300px; grid-template-columns: 1fr 360px; gap: 1em; align-items: start; } Loading editor/html/index.html +1 −1 Changes for editor/html/index.html: 1 added line, 1 removed line. Original line number Diff line number Diff line Loading @@ -438,7 +438,7 @@ <strong style="font-size:0.85rem">Fragebaum</strong> <button id="btn-sm-add-question" class="set-save-btn" style="padding:0.15em 0.5em;font-size:0.8rem">+ Frage hinzufügen</button> </div> <div style="overflow:auto;border:1px solid var(--border);border-radius:6px;background:var(--bg-primary);min-height:160px"> <div style="overflow:auto;border:1px solid var(--border);border-radius:6px;background:var(--bg-primary);min-height:420px"> <canvas id="sm-canvas"></canvas> </div> </div> Loading editor/src/webedit_api.cpp +48 −45 Changes for editor/src/webedit_api.cpp: 48 added lines, 45 removed lines. Original line number Diff line number Diff line Loading @@ -2165,7 +2165,7 @@ void webedit::Api::handleSaveDocument(libhttppp::HttpRequest &curreq, if (doc.currentDocId.empty()) { std::string existingId; const bool hasConflict = _db.findDocumentIdByNameGroup(uid, domain, doc.currentDocName, const bool hasConflict = _db.findDocumentIdByNameGroup(domain, doc.currentDocName, doc.currentDocGroup, existingId); if (hasConflict && !overwrite) { json_object *resp = json_object_new_object(); Loading @@ -2179,13 +2179,13 @@ void webedit::Api::handleSaveDocument(libhttppp::HttpRequest &curreq, return; } if (hasConflict) { docId = _db.updateDocument(uid, existingId, doc.currentDocName, xml, author, doc.currentDocGroup); docId = _db.updateDocument(domain, existingId, doc.currentDocName, xml, author, doc.currentDocGroup); } else { docId = _db.saveDocument(uid, domain, doc.currentDocName, xml, author, doc.currentDocGroup); } doc.currentDocId = docId; } else { docId = _db.updateDocument(uid, doc.currentDocId, doc.currentDocName, xml, author, doc.currentDocGroup); docId = _db.updateDocument(domain, doc.currentDocId, doc.currentDocName, xml, author, doc.currentDocGroup); } json_object *resp = json_object_new_object(); Loading Loading @@ -2242,7 +2242,7 @@ void webedit::Api::handleSaveDocumentAs(libhttppp::HttpRequest &curreq, _session.getData(sessionid, "domain", domain); std::string existingId; const bool hasConflict = _db.findDocumentIdByNameGroup(uid, domain, doc.currentDocName, const bool hasConflict = _db.findDocumentIdByNameGroup(domain, doc.currentDocName, doc.currentDocGroup, existingId); if (hasConflict && !overwrite) { json_object *resp = json_object_new_object(); Loading @@ -2260,7 +2260,7 @@ void webedit::Api::handleSaveDocumentAs(libhttppp::HttpRequest &curreq, // the same name in the same group — the open document then becomes // that document, matching classic "Save As" semantics. std::string docId = hasConflict ? _db.updateDocument(uid, existingId, doc.currentDocName, xml, author, doc.currentDocGroup) ? _db.updateDocument(domain, existingId, doc.currentDocName, xml, author, doc.currentDocGroup) : _db.saveDocument(uid, domain, doc.currentDocName, xml, author, doc.currentDocGroup); doc.currentDocId = docId; Loading Loading @@ -2350,7 +2350,7 @@ void webedit::Api::handleTemplateBulkGenerate(libhttppp::HttpRequest &curreq, TemplateData t; t.id = idStr; if (!_db.loadDocument(uid, t.id, t.name, t.xml, t.group)) { if (!_db.loadDocument(sessionDomain, t.id, t.name, t.xml, t.group)) { continue; } templates.push_back(std::move(t)); Loading Loading @@ -2401,8 +2401,7 @@ void webedit::Api::handleTemplateBulkGenerate(libhttppp::HttpRequest &curreq, const std::string targetGroup = rowDomain.empty() ? tpl.group : rowDomain; std::string existingDocId; const bool exists = _db.findDocumentIdByNameGroup(uid, sessionDomain, const bool exists = _db.findDocumentIdByNameGroup(sessionDomain, tpl.name, targetGroup, existingDocId); Loading Loading @@ -2439,7 +2438,7 @@ void webedit::Api::handleTemplateBulkGenerate(libhttppp::HttpRequest &curreq, std::string changedDocId; bool updated = false; if (exists && overwriteExisting) { changedDocId = _db.updateDocument(uid, changedDocId = _db.updateDocument(sessionDomain, existingDocId, tpl.name, generatedXml, Loading Loading @@ -2497,7 +2496,7 @@ void webedit::Api::handleListTemplates(libhttppp::HttpRequest &curreq, return; } std::string jsonStr = _db.listDocumentsForOwnerDomain(uid, domain); std::string jsonStr = _db.listDocuments(domain); json_object *arr = json_tokener_parse(jsonStr.c_str()); if (!arr) { arr = json_object_new_array(); Loading @@ -2514,11 +2513,11 @@ void webedit::Api::handleListTemplates(libhttppp::HttpRequest &curreq, void webedit::Api::handleLoadDocument(libhttppp::HttpRequest &curreq, const std::string &sessionid, const std::string &docId) { std::string uid; _session.getData(sessionid, "uid", uid); std::string domain; _session.getData(sessionid, "domain", domain); std::string name, xml, group; if (!_db.loadDocument(uid, docId, name, xml, group)) { if (!_db.loadDocument(domain, docId, name, xml, group)) { sendJsonError(curreq, 404, "Document not found"); return; } Loading Loading @@ -2563,9 +2562,12 @@ void webedit::Api::handleListDocuments(libhttppp::HttpRequest &curreq, void webedit::Api::handleDeleteDocument(libhttppp::HttpRequest &curreq, const std::string &sessionid, const std::string &docId) { std::string uid; _session.getData(sessionid, "uid", uid); _db.deleteDocument(uid, docId); std::string domain; _session.getData(sessionid, "domain", domain); if (!_db.deleteDocument(domain, docId)) { sendJsonError(curreq, 404, "Document not found"); return; } json_object *resp = json_object_new_object(); json_object_object_add(resp, "status", json_object_new_string("ok")); sendJson(curreq, resp); Loading Loading @@ -2632,10 +2634,10 @@ void webedit::Api::handleRestoreRevision(libhttppp::HttpRequest &curreq, std::string docId = json_object_get_string(docIdObj); std::string revId = json_object_get_string(revIdObj); std::string uid; _session.getData(sessionid, "uid", uid); std::string domain; _session.getData(sessionid, "domain", domain); if (!_db.restoreRevision(uid, docId, revId)) { if (!_db.restoreRevision(domain, docId, revId)) { sendJsonError(curreq, 404, "Revision not found"); if (req) json_object_put(req); return; Loading @@ -2643,7 +2645,7 @@ void webedit::Api::handleRestoreRevision(libhttppp::HttpRequest &curreq, // Reload the restored version into session std::string name, xml, group; _db.loadDocument(uid, docId, name, xml, group); _db.loadDocument(domain, docId, name, xml, group); auto &doc = getDocState(sessionid); std::lock_guard<std::mutex> lk(doc.mtx); Loading Loading @@ -3422,10 +3424,10 @@ void webedit::Api::handlePublishToConnection(libhttppp::HttpRequest &curreq, // Auto-publish surveys embedded in this document to the target blogi first, // so they exist server-side before the rendered HTML references them. { std::string uid; _session.getData(sessionid, "uid", uid); std::string domain; _session.getData(sessionid, "domain", domain); std::string docXml = exportTreeXml(doc); autoPublishSurveysForDocument(docXml, authid, blogUrl, uid); autoPublishSurveysForDocument(docXml, authid, blogUrl, domain); } std::string html = renderTree(doc.root); Loading Loading @@ -4205,7 +4207,7 @@ json_object* webedit::Api::surveyXmlToJson(const std::string &name, void webedit::Api::autoPublishSurveysForDocument(const std::string &docXml, const std::string &authid, const std::string &blogUrl, const std::string &ownerUid) { const std::string &domain) { if (docXml.empty() || authid.empty() || blogUrl.empty()) return; tinyxml2::XMLDocument doc; Loading @@ -4231,9 +4233,9 @@ void webedit::Api::autoPublishSurveysForDocument(const std::string &docXml, for (const auto &sname : surveyNames) { dbpp::SQL sql; dbpp::DBResult res; std::vector<char> eOwner, eName; sql << "SELECT id, name, title, xml FROM survey_templates WHERE owner_uid='" << dbpp::SQL::escaped(eOwner, ownerUid.c_str()) << "' AND name='" std::vector<char> eDomain, eName; sql << "SELECT id, name, title, xml FROM survey_templates WHERE domain='" << dbpp::SQL::escaped(eDomain, domain.c_str()) << "' AND name='" << dbpp::SQL::escaped(eName, sname.c_str()) << "' LIMIT 1;"; int rows = _db.getDb().exec(sql, res); Loading Loading @@ -4273,9 +4275,9 @@ void webedit::Api::autoPublishSurveysForDocument(const std::string &docXml, void webedit::Api::handleListSurveys(libhttppp::HttpRequest &curreq, const std::string &sessionid) { std::string uid; _session.getData(sessionid, "uid", uid); std::string jsonStr = _db.listSurveys(uid); std::string domain; _session.getData(sessionid, "domain", domain); std::string jsonStr = _db.listSurveys(domain); json_object *resp = json_object_new_object(); json_object *arr = json_tokener_parse(jsonStr.c_str()); json_object_object_add(resp, "surveys", arr ? arr : json_object_new_array()); Loading Loading @@ -4337,9 +4339,9 @@ void webedit::Api::handleListDocumentSections(libhttppp::HttpRequest &curreq, void webedit::Api::handleListSurveyNames(libhttppp::HttpRequest &curreq, const std::string &sessionid) { std::string uid; _session.getData(sessionid, "uid", uid); std::string jsonStr = _db.listSurveyNames(uid); std::string domain; _session.getData(sessionid, "domain", domain); std::string jsonStr = _db.listSurveyNames(domain); json_object *resp = json_object_new_object(); json_object *arr = json_tokener_parse(jsonStr.c_str()); json_object_object_add(resp, "surveys", arr ? arr : json_object_new_array()); Loading @@ -4350,9 +4352,9 @@ void webedit::Api::handleListSurveyNames(libhttppp::HttpRequest &curreq, void webedit::Api::handleGetSurvey(libhttppp::HttpRequest &curreq, const std::string &sessionid, const std::string &surveyId) { std::string uid; _session.getData(sessionid, "uid", uid); std::string jsonStr = _db.getSurvey(uid, surveyId); std::string domain; _session.getData(sessionid, "domain", domain); std::string jsonStr = _db.getSurvey(domain, surveyId); json_object *resp = json_tokener_parse(jsonStr.c_str()); if (!resp) { sendJsonError(curreq, 404, "Survey not found"); Loading @@ -4364,8 +4366,9 @@ void webedit::Api::handleGetSurvey(libhttppp::HttpRequest &curreq, void webedit::Api::handleSaveSurvey(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()); Loading Loading @@ -4393,9 +4396,9 @@ void webedit::Api::handleSaveSurvey(libhttppp::HttpRequest &curreq, std::string surveyId; if (idObj && strlen(json_object_get_string(idObj)) > 0) { surveyId = json_object_get_string(idObj); _db.updateSurvey(uid, surveyId, name, title, xml); _db.updateSurvey(domain, surveyId, name, title, xml); } else { surveyId = _db.saveSurvey(uid, name, title, xml); surveyId = _db.saveSurvey(uid, domain, name, title, xml); } json_object *resp = json_object_new_object(); Loading @@ -4409,9 +4412,9 @@ void webedit::Api::handleSaveSurvey(libhttppp::HttpRequest &curreq, void webedit::Api::handleDeleteSurvey(libhttppp::HttpRequest &curreq, const std::string &sessionid, const std::string &surveyId) { std::string uid; _session.getData(sessionid, "uid", uid); _db.deleteSurvey(uid, surveyId); std::string domain; _session.getData(sessionid, "domain", domain); _db.deleteSurvey(domain, surveyId); json_object *resp = json_object_new_object(); json_object_object_add(resp, "status", json_object_new_string("ok")); sendJson(curreq, resp); Loading @@ -4420,8 +4423,8 @@ void webedit::Api::handleDeleteSurvey(libhttppp::HttpRequest &curreq, void webedit::Api::handlePublishSurveyToConnection(libhttppp::HttpRequest &curreq, const std::string &sessionid) { std::string uid; _session.getData(sessionid, "uid", uid); std::string domain; _session.getData(sessionid, "domain", domain); std::string body = getRequestBody(curreq); json_object *req = json_tokener_parse(body.c_str()); Loading @@ -4443,7 +4446,7 @@ void webedit::Api::handlePublishSurveyToConnection(libhttppp::HttpRequest &curre return; } std::string surveyJson = _db.getSurvey(uid, surveyId); std::string surveyJson = _db.getSurvey(domain, surveyId); json_object *surveyData = json_tokener_parse(surveyJson.c_str()); if (!surveyData) { sendJsonError(curreq, 404, "Survey not found"); Loading editor/src/webedit_db.cpp +48 −76 Changes for editor/src/webedit_db.cpp: 48 added lines, 76 removed lines. Original line number Diff line number Diff line Loading @@ -180,6 +180,7 @@ void webedit::Database::initTables() { sql << "CREATE TABLE IF NOT EXISTS survey_templates(" << "id " << uuidType << "," << "owner_uid varchar(255) NOT NULL," << "domain varchar(255) NOT NULL DEFAULT ''," << "name varchar(255) NOT NULL," << "title varchar(255) NOT NULL DEFAULT ''," << "xml " << longTextType << " NOT NULL," Loading @@ -205,6 +206,7 @@ void webedit::Database::initTables() { 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 document_revisions ADD COLUMN author varchar(255) DEFAULT ''"); tryAlter("ALTER TABLE survey_templates ADD COLUMN domain varchar(255) NOT NULL DEFAULT ''"); } std::string webedit::Database::getOption(const std::string &key, Loading Loading @@ -295,7 +297,7 @@ std::string webedit::Database::saveDocument(const std::string &ownerUid, return docId.c_str(); } std::string webedit::Database::updateDocument(const std::string &ownerUid, std::string webedit::Database::updateDocument(const std::string &domain, const std::string &id, const std::string &name, const std::string &xml, Loading @@ -303,7 +305,7 @@ std::string webedit::Database::updateDocument(const std::string &ownerUid, const std::string &group) { dbpp::SQL sql; dbpp::DBResult res; std::vector<char> escapedName, escapedXml, escapedId, escapedUid, escapedGroup; std::vector<char> escapedName, escapedXml, escapedId, escapedDomain, escapedGroup; sql << "UPDATE documents SET group_name='" << dbpp::SQL::escaped(escapedGroup, group.c_str()) << "', name='" Loading @@ -311,8 +313,8 @@ std::string webedit::Database::updateDocument(const std::string &ownerUid, << dbpp::SQL::escaped(escapedXml, xml.c_str()) << "', modified=CURRENT_TIMESTAMP WHERE id='" << dbpp::SQL::escaped(escapedId, id.c_str()) << "' AND owner_uid='" << dbpp::SQL::escaped(escapedUid, ownerUid.c_str()) << "';"; << "' AND domain='" << dbpp::SQL::escaped(escapedDomain, domain.c_str()) << "';"; _db->exec(sql, res); Loading Loading @@ -353,18 +355,18 @@ std::string webedit::Database::updateDocument(const std::string &ownerUid, return id; } bool webedit::Database::loadDocument(const std::string &ownerUid, bool webedit::Database::loadDocument(const std::string &domain, const std::string &id, std::string &name, std::string &xml, std::string &group) { dbpp::SQL sql; dbpp::DBResult res; std::vector<char> escapedId, escapedUid; std::vector<char> escapedId, escapedDomain; sql << "SELECT name, xml, group_name FROM documents WHERE id='" << dbpp::SQL::escaped(escapedId, id.c_str()) << "' AND owner_uid='" << dbpp::SQL::escaped(escapedUid, ownerUid.c_str()) << "';"; << "' AND domain='" << dbpp::SQL::escaped(escapedDomain, domain.c_str()) << "';"; int rows = _db->exec(sql, res); if (rows < 1) Loading @@ -376,17 +378,17 @@ bool webedit::Database::loadDocument(const std::string &ownerUid, return true; } bool webedit::Database::deleteDocument(const std::string &ownerUid, bool webedit::Database::deleteDocument(const std::string &domain, const std::string &id) { dbpp::SQL sql; dbpp::DBResult res; std::vector<char> escapedId, escapedUid; std::vector<char> escapedId, escapedDomain; // Verify ownership before deleting // Verify the document belongs to the caller's domain before deleting sql << "SELECT id FROM documents WHERE id='" << dbpp::SQL::escaped(escapedId, id.c_str()) << "' AND owner_uid='" << dbpp::SQL::escaped(escapedUid, ownerUid.c_str()) << "';"; << "' AND domain='" << dbpp::SQL::escaped(escapedDomain, domain.c_str()) << "';"; int rows = _db->exec(sql, res); if (rows < 1) Loading @@ -404,12 +406,12 @@ bool webedit::Database::deleteDocument(const std::string &ownerUid, sql.clear(); res.clear(); escapedId.clear(); escapedUid.clear(); escapedDomain.clear(); sql << "DELETE FROM documents WHERE id='" << dbpp::SQL::escaped(escapedId, id.c_str()) << "' AND owner_uid='" << dbpp::SQL::escaped(escapedUid, ownerUid.c_str()) << "';"; << "' AND domain='" << dbpp::SQL::escaped(escapedDomain, domain.c_str()) << "';"; _db->exec(sql, res); return true; Loading Loading @@ -443,48 +445,16 @@ std::string webedit::Database::listDocuments(const std::string &domain) { return result; } std::string webedit::Database::listDocumentsForOwnerDomain(const std::string &ownerUid, const std::string &domain) { dbpp::SQL sql; dbpp::DBResult res; std::vector<char> escapedUid, escapedDomain; sql << "SELECT id, name, created, modified, group_name FROM documents " << "WHERE owner_uid='" << dbpp::SQL::escaped(escapedUid, ownerUid.c_str()) << "' AND domain='" << dbpp::SQL::escaped(escapedDomain, domain.c_str()) << "' ORDER BY group_name, name, modified DESC;"; int rows = _db->exec(sql, res); json_object *arr = json_object_new_array(); for (int i = 0; i < rows; ++i) { json_object *obj = json_object_new_object(); json_object_object_add(obj, "id", json_object_new_string(res[i][0])); json_object_object_add(obj, "name", json_object_new_string(res[i][1])); json_object_object_add(obj, "created", json_object_new_string(res[i][2])); json_object_object_add(obj, "modified", json_object_new_string(res[i][3])); json_object_object_add(obj, "group", json_object_new_string(res[i][4])); json_object_array_add(arr, obj); } std::string result = json_object_to_json_string_ext(arr, JSON_C_TO_STRING_NOSLASHESCAPE); json_object_put(arr); return result; } bool webedit::Database::findDocumentIdByNameGroup(const std::string &ownerUid, const std::string &domain, bool webedit::Database::findDocumentIdByNameGroup(const std::string &domain, const std::string &name, const std::string &group, std::string &docId) { dbpp::SQL sql; dbpp::DBResult res; std::vector<char> escapedUid, escapedDomain, escapedName, escapedGroup; std::vector<char> escapedDomain, escapedName, escapedGroup; sql << "SELECT id FROM documents WHERE owner_uid='" << dbpp::SQL::escaped(escapedUid, ownerUid.c_str()) << "' AND domain='" << dbpp::SQL::escaped(escapedDomain, domain.c_str()) sql << "SELECT id FROM documents WHERE domain='" << dbpp::SQL::escaped(escapedDomain, domain.c_str()) << "' AND name='" << dbpp::SQL::escaped(escapedName, name.c_str()) << "' AND group_name='" << dbpp::SQL::escaped(escapedGroup, group.c_str()) << "' ORDER BY modified DESC LIMIT 1;"; Loading Loading @@ -545,14 +515,14 @@ bool webedit::Database::loadRevision(const std::string &revisionId, return true; } bool webedit::Database::restoreRevision(const std::string &ownerUid, bool webedit::Database::restoreRevision(const std::string &domain, const std::string &docId, const std::string &revisionId) { std::string name, xml; if (!loadRevision(revisionId, name, xml)) return false; updateDocument(ownerUid, docId, name, xml); updateDocument(domain, docId, name, xml); return true; } Loading Loading @@ -731,6 +701,7 @@ void webedit::Database::clearChatMessages(const std::string &ownerUid) { // --------------------------------------------------------------------------- std::string webedit::Database::saveSurvey(const std::string &ownerUid, const std::string &domain, const std::string &name, const std::string &title, const std::string &xml) { Loading @@ -739,11 +710,12 @@ std::string webedit::Database::saveSurvey(const std::string &ownerUid, dbpp::SQL sql; dbpp::DBResult res; std::vector<char> eOwner, eName, eTitle, eXml; std::vector<char> eOwner, eDomain, eName, eTitle, eXml; sql << "INSERT INTO survey_templates (id, owner_uid, name, title, xml) VALUES ('" sql << "INSERT INTO survey_templates (id, owner_uid, domain, name, title, xml) VALUES ('" << id.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(eTitle, title.c_str()) << "','" << dbpp::SQL::escaped(eXml, xml.c_str()) << "');"; Loading @@ -752,45 +724,45 @@ std::string webedit::Database::saveSurvey(const std::string &ownerUid, return std::string(id.c_str()); } bool webedit::Database::updateSurvey(const std::string &ownerUid, const std::string &id, bool webedit::Database::updateSurvey(const std::string &domain, const std::string &id, const std::string &name, const std::string &title, const std::string &xml) { dbpp::SQL sql; dbpp::DBResult res; std::vector<char> eOwner, eId, eName, eTitle, eXml; std::vector<char> eDomain, eId, eName, eTitle, eXml; sql << "UPDATE survey_templates SET name='" << dbpp::SQL::escaped(eName, name.c_str()) << "', title='" << dbpp::SQL::escaped(eTitle, title.c_str()) << "', xml='" << dbpp::SQL::escaped(eXml, xml.c_str()) << "', modified=CURRENT_TIMESTAMP 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; } bool webedit::Database::deleteSurvey(const std::string &ownerUid, const std::string &id) { bool webedit::Database::deleteSurvey(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 survey_templates 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::listSurveys(const std::string &ownerUid) { std::string webedit::Database::listSurveys(const std::string &domain) { dbpp::SQL sql; dbpp::DBResult res; std::vector<char> eOwner; std::vector<char> eDomain; sql << "SELECT id, name, title, created, modified " << "FROM survey_templates WHERE owner_uid='" << dbpp::SQL::escaped(eOwner, ownerUid.c_str()) << "FROM survey_templates WHERE domain='" << dbpp::SQL::escaped(eDomain, domain.c_str()) << "' ORDER BY name;"; int rows = _db->exec(sql, res); Loading @@ -810,13 +782,13 @@ std::string webedit::Database::listSurveys(const std::string &ownerUid) { return result; } std::string webedit::Database::listSurveyNames(const std::string &ownerUid) { std::string webedit::Database::listSurveyNames(const std::string &domain) { dbpp::SQL sql; dbpp::DBResult res; std::vector<char> eOwner; std::vector<char> eDomain; sql << "SELECT id, name FROM survey_templates WHERE owner_uid='" << dbpp::SQL::escaped(eOwner, ownerUid.c_str()) << "' ORDER BY name;"; sql << "SELECT id, name FROM survey_templates WHERE domain='" << dbpp::SQL::escaped(eDomain, domain.c_str()) << "' ORDER BY name;"; int rows = _db->exec(sql, res); json_object *arr = json_object_new_array(); Loading @@ -832,15 +804,15 @@ std::string webedit::Database::listSurveyNames(const std::string &ownerUid) { return result; } std::string webedit::Database::getSurvey(const std::string &ownerUid, const std::string &id) { std::string webedit::Database::getSurvey(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 << "SELECT id, name, title, xml, created, modified " << "FROM survey_templates 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 "{}"; Loading editor/src/webedit_db.h +14 −16 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
editor/html/css/editor.css +5 −5 Changes for editor/html/css/editor.css: 5 added lines, 5 removed lines. Original line number Diff line number Diff line Loading @@ -1403,16 +1403,16 @@ dialog label { ============================================================ */ .survey-manager-dialog { width: min(92vw, 960px); max-height: 90vh; width: min(96vw, 1400px); max-height: 92vh; } .survey-manager-dialog .set-modal { min-height: 480px; min-height: 700px; } .sm-survey-list { max-height: 300px; max-height: 520px; overflow-y: auto; } Loading Loading @@ -1444,7 +1444,7 @@ dialog label { .sm-editor-layout { display: grid; grid-template-columns: 1fr 300px; grid-template-columns: 1fr 360px; gap: 1em; align-items: start; } Loading
editor/html/index.html +1 −1 Changes for editor/html/index.html: 1 added line, 1 removed line. Original line number Diff line number Diff line Loading @@ -438,7 +438,7 @@ <strong style="font-size:0.85rem">Fragebaum</strong> <button id="btn-sm-add-question" class="set-save-btn" style="padding:0.15em 0.5em;font-size:0.8rem">+ Frage hinzufügen</button> </div> <div style="overflow:auto;border:1px solid var(--border);border-radius:6px;background:var(--bg-primary);min-height:160px"> <div style="overflow:auto;border:1px solid var(--border);border-radius:6px;background:var(--bg-primary);min-height:420px"> <canvas id="sm-canvas"></canvas> </div> </div> Loading
editor/src/webedit_api.cpp +48 −45 Changes for editor/src/webedit_api.cpp: 48 added lines, 45 removed lines. Original line number Diff line number Diff line Loading @@ -2165,7 +2165,7 @@ void webedit::Api::handleSaveDocument(libhttppp::HttpRequest &curreq, if (doc.currentDocId.empty()) { std::string existingId; const bool hasConflict = _db.findDocumentIdByNameGroup(uid, domain, doc.currentDocName, const bool hasConflict = _db.findDocumentIdByNameGroup(domain, doc.currentDocName, doc.currentDocGroup, existingId); if (hasConflict && !overwrite) { json_object *resp = json_object_new_object(); Loading @@ -2179,13 +2179,13 @@ void webedit::Api::handleSaveDocument(libhttppp::HttpRequest &curreq, return; } if (hasConflict) { docId = _db.updateDocument(uid, existingId, doc.currentDocName, xml, author, doc.currentDocGroup); docId = _db.updateDocument(domain, existingId, doc.currentDocName, xml, author, doc.currentDocGroup); } else { docId = _db.saveDocument(uid, domain, doc.currentDocName, xml, author, doc.currentDocGroup); } doc.currentDocId = docId; } else { docId = _db.updateDocument(uid, doc.currentDocId, doc.currentDocName, xml, author, doc.currentDocGroup); docId = _db.updateDocument(domain, doc.currentDocId, doc.currentDocName, xml, author, doc.currentDocGroup); } json_object *resp = json_object_new_object(); Loading Loading @@ -2242,7 +2242,7 @@ void webedit::Api::handleSaveDocumentAs(libhttppp::HttpRequest &curreq, _session.getData(sessionid, "domain", domain); std::string existingId; const bool hasConflict = _db.findDocumentIdByNameGroup(uid, domain, doc.currentDocName, const bool hasConflict = _db.findDocumentIdByNameGroup(domain, doc.currentDocName, doc.currentDocGroup, existingId); if (hasConflict && !overwrite) { json_object *resp = json_object_new_object(); Loading @@ -2260,7 +2260,7 @@ void webedit::Api::handleSaveDocumentAs(libhttppp::HttpRequest &curreq, // the same name in the same group — the open document then becomes // that document, matching classic "Save As" semantics. std::string docId = hasConflict ? _db.updateDocument(uid, existingId, doc.currentDocName, xml, author, doc.currentDocGroup) ? _db.updateDocument(domain, existingId, doc.currentDocName, xml, author, doc.currentDocGroup) : _db.saveDocument(uid, domain, doc.currentDocName, xml, author, doc.currentDocGroup); doc.currentDocId = docId; Loading Loading @@ -2350,7 +2350,7 @@ void webedit::Api::handleTemplateBulkGenerate(libhttppp::HttpRequest &curreq, TemplateData t; t.id = idStr; if (!_db.loadDocument(uid, t.id, t.name, t.xml, t.group)) { if (!_db.loadDocument(sessionDomain, t.id, t.name, t.xml, t.group)) { continue; } templates.push_back(std::move(t)); Loading Loading @@ -2401,8 +2401,7 @@ void webedit::Api::handleTemplateBulkGenerate(libhttppp::HttpRequest &curreq, const std::string targetGroup = rowDomain.empty() ? tpl.group : rowDomain; std::string existingDocId; const bool exists = _db.findDocumentIdByNameGroup(uid, sessionDomain, const bool exists = _db.findDocumentIdByNameGroup(sessionDomain, tpl.name, targetGroup, existingDocId); Loading Loading @@ -2439,7 +2438,7 @@ void webedit::Api::handleTemplateBulkGenerate(libhttppp::HttpRequest &curreq, std::string changedDocId; bool updated = false; if (exists && overwriteExisting) { changedDocId = _db.updateDocument(uid, changedDocId = _db.updateDocument(sessionDomain, existingDocId, tpl.name, generatedXml, Loading Loading @@ -2497,7 +2496,7 @@ void webedit::Api::handleListTemplates(libhttppp::HttpRequest &curreq, return; } std::string jsonStr = _db.listDocumentsForOwnerDomain(uid, domain); std::string jsonStr = _db.listDocuments(domain); json_object *arr = json_tokener_parse(jsonStr.c_str()); if (!arr) { arr = json_object_new_array(); Loading @@ -2514,11 +2513,11 @@ void webedit::Api::handleListTemplates(libhttppp::HttpRequest &curreq, void webedit::Api::handleLoadDocument(libhttppp::HttpRequest &curreq, const std::string &sessionid, const std::string &docId) { std::string uid; _session.getData(sessionid, "uid", uid); std::string domain; _session.getData(sessionid, "domain", domain); std::string name, xml, group; if (!_db.loadDocument(uid, docId, name, xml, group)) { if (!_db.loadDocument(domain, docId, name, xml, group)) { sendJsonError(curreq, 404, "Document not found"); return; } Loading Loading @@ -2563,9 +2562,12 @@ void webedit::Api::handleListDocuments(libhttppp::HttpRequest &curreq, void webedit::Api::handleDeleteDocument(libhttppp::HttpRequest &curreq, const std::string &sessionid, const std::string &docId) { std::string uid; _session.getData(sessionid, "uid", uid); _db.deleteDocument(uid, docId); std::string domain; _session.getData(sessionid, "domain", domain); if (!_db.deleteDocument(domain, docId)) { sendJsonError(curreq, 404, "Document not found"); return; } json_object *resp = json_object_new_object(); json_object_object_add(resp, "status", json_object_new_string("ok")); sendJson(curreq, resp); Loading Loading @@ -2632,10 +2634,10 @@ void webedit::Api::handleRestoreRevision(libhttppp::HttpRequest &curreq, std::string docId = json_object_get_string(docIdObj); std::string revId = json_object_get_string(revIdObj); std::string uid; _session.getData(sessionid, "uid", uid); std::string domain; _session.getData(sessionid, "domain", domain); if (!_db.restoreRevision(uid, docId, revId)) { if (!_db.restoreRevision(domain, docId, revId)) { sendJsonError(curreq, 404, "Revision not found"); if (req) json_object_put(req); return; Loading @@ -2643,7 +2645,7 @@ void webedit::Api::handleRestoreRevision(libhttppp::HttpRequest &curreq, // Reload the restored version into session std::string name, xml, group; _db.loadDocument(uid, docId, name, xml, group); _db.loadDocument(domain, docId, name, xml, group); auto &doc = getDocState(sessionid); std::lock_guard<std::mutex> lk(doc.mtx); Loading Loading @@ -3422,10 +3424,10 @@ void webedit::Api::handlePublishToConnection(libhttppp::HttpRequest &curreq, // Auto-publish surveys embedded in this document to the target blogi first, // so they exist server-side before the rendered HTML references them. { std::string uid; _session.getData(sessionid, "uid", uid); std::string domain; _session.getData(sessionid, "domain", domain); std::string docXml = exportTreeXml(doc); autoPublishSurveysForDocument(docXml, authid, blogUrl, uid); autoPublishSurveysForDocument(docXml, authid, blogUrl, domain); } std::string html = renderTree(doc.root); Loading Loading @@ -4205,7 +4207,7 @@ json_object* webedit::Api::surveyXmlToJson(const std::string &name, void webedit::Api::autoPublishSurveysForDocument(const std::string &docXml, const std::string &authid, const std::string &blogUrl, const std::string &ownerUid) { const std::string &domain) { if (docXml.empty() || authid.empty() || blogUrl.empty()) return; tinyxml2::XMLDocument doc; Loading @@ -4231,9 +4233,9 @@ void webedit::Api::autoPublishSurveysForDocument(const std::string &docXml, for (const auto &sname : surveyNames) { dbpp::SQL sql; dbpp::DBResult res; std::vector<char> eOwner, eName; sql << "SELECT id, name, title, xml FROM survey_templates WHERE owner_uid='" << dbpp::SQL::escaped(eOwner, ownerUid.c_str()) << "' AND name='" std::vector<char> eDomain, eName; sql << "SELECT id, name, title, xml FROM survey_templates WHERE domain='" << dbpp::SQL::escaped(eDomain, domain.c_str()) << "' AND name='" << dbpp::SQL::escaped(eName, sname.c_str()) << "' LIMIT 1;"; int rows = _db.getDb().exec(sql, res); Loading Loading @@ -4273,9 +4275,9 @@ void webedit::Api::autoPublishSurveysForDocument(const std::string &docXml, void webedit::Api::handleListSurveys(libhttppp::HttpRequest &curreq, const std::string &sessionid) { std::string uid; _session.getData(sessionid, "uid", uid); std::string jsonStr = _db.listSurveys(uid); std::string domain; _session.getData(sessionid, "domain", domain); std::string jsonStr = _db.listSurveys(domain); json_object *resp = json_object_new_object(); json_object *arr = json_tokener_parse(jsonStr.c_str()); json_object_object_add(resp, "surveys", arr ? arr : json_object_new_array()); Loading Loading @@ -4337,9 +4339,9 @@ void webedit::Api::handleListDocumentSections(libhttppp::HttpRequest &curreq, void webedit::Api::handleListSurveyNames(libhttppp::HttpRequest &curreq, const std::string &sessionid) { std::string uid; _session.getData(sessionid, "uid", uid); std::string jsonStr = _db.listSurveyNames(uid); std::string domain; _session.getData(sessionid, "domain", domain); std::string jsonStr = _db.listSurveyNames(domain); json_object *resp = json_object_new_object(); json_object *arr = json_tokener_parse(jsonStr.c_str()); json_object_object_add(resp, "surveys", arr ? arr : json_object_new_array()); Loading @@ -4350,9 +4352,9 @@ void webedit::Api::handleListSurveyNames(libhttppp::HttpRequest &curreq, void webedit::Api::handleGetSurvey(libhttppp::HttpRequest &curreq, const std::string &sessionid, const std::string &surveyId) { std::string uid; _session.getData(sessionid, "uid", uid); std::string jsonStr = _db.getSurvey(uid, surveyId); std::string domain; _session.getData(sessionid, "domain", domain); std::string jsonStr = _db.getSurvey(domain, surveyId); json_object *resp = json_tokener_parse(jsonStr.c_str()); if (!resp) { sendJsonError(curreq, 404, "Survey not found"); Loading @@ -4364,8 +4366,9 @@ void webedit::Api::handleGetSurvey(libhttppp::HttpRequest &curreq, void webedit::Api::handleSaveSurvey(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()); Loading Loading @@ -4393,9 +4396,9 @@ void webedit::Api::handleSaveSurvey(libhttppp::HttpRequest &curreq, std::string surveyId; if (idObj && strlen(json_object_get_string(idObj)) > 0) { surveyId = json_object_get_string(idObj); _db.updateSurvey(uid, surveyId, name, title, xml); _db.updateSurvey(domain, surveyId, name, title, xml); } else { surveyId = _db.saveSurvey(uid, name, title, xml); surveyId = _db.saveSurvey(uid, domain, name, title, xml); } json_object *resp = json_object_new_object(); Loading @@ -4409,9 +4412,9 @@ void webedit::Api::handleSaveSurvey(libhttppp::HttpRequest &curreq, void webedit::Api::handleDeleteSurvey(libhttppp::HttpRequest &curreq, const std::string &sessionid, const std::string &surveyId) { std::string uid; _session.getData(sessionid, "uid", uid); _db.deleteSurvey(uid, surveyId); std::string domain; _session.getData(sessionid, "domain", domain); _db.deleteSurvey(domain, surveyId); json_object *resp = json_object_new_object(); json_object_object_add(resp, "status", json_object_new_string("ok")); sendJson(curreq, resp); Loading @@ -4420,8 +4423,8 @@ void webedit::Api::handleDeleteSurvey(libhttppp::HttpRequest &curreq, void webedit::Api::handlePublishSurveyToConnection(libhttppp::HttpRequest &curreq, const std::string &sessionid) { std::string uid; _session.getData(sessionid, "uid", uid); std::string domain; _session.getData(sessionid, "domain", domain); std::string body = getRequestBody(curreq); json_object *req = json_tokener_parse(body.c_str()); Loading @@ -4443,7 +4446,7 @@ void webedit::Api::handlePublishSurveyToConnection(libhttppp::HttpRequest &curre return; } std::string surveyJson = _db.getSurvey(uid, surveyId); std::string surveyJson = _db.getSurvey(domain, surveyId); json_object *surveyData = json_tokener_parse(surveyJson.c_str()); if (!surveyData) { sendJsonError(curreq, 404, "Survey not found"); Loading
editor/src/webedit_db.cpp +48 −76 Changes for editor/src/webedit_db.cpp: 48 added lines, 76 removed lines. Original line number Diff line number Diff line Loading @@ -180,6 +180,7 @@ void webedit::Database::initTables() { sql << "CREATE TABLE IF NOT EXISTS survey_templates(" << "id " << uuidType << "," << "owner_uid varchar(255) NOT NULL," << "domain varchar(255) NOT NULL DEFAULT ''," << "name varchar(255) NOT NULL," << "title varchar(255) NOT NULL DEFAULT ''," << "xml " << longTextType << " NOT NULL," Loading @@ -205,6 +206,7 @@ void webedit::Database::initTables() { 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 document_revisions ADD COLUMN author varchar(255) DEFAULT ''"); tryAlter("ALTER TABLE survey_templates ADD COLUMN domain varchar(255) NOT NULL DEFAULT ''"); } std::string webedit::Database::getOption(const std::string &key, Loading Loading @@ -295,7 +297,7 @@ std::string webedit::Database::saveDocument(const std::string &ownerUid, return docId.c_str(); } std::string webedit::Database::updateDocument(const std::string &ownerUid, std::string webedit::Database::updateDocument(const std::string &domain, const std::string &id, const std::string &name, const std::string &xml, Loading @@ -303,7 +305,7 @@ std::string webedit::Database::updateDocument(const std::string &ownerUid, const std::string &group) { dbpp::SQL sql; dbpp::DBResult res; std::vector<char> escapedName, escapedXml, escapedId, escapedUid, escapedGroup; std::vector<char> escapedName, escapedXml, escapedId, escapedDomain, escapedGroup; sql << "UPDATE documents SET group_name='" << dbpp::SQL::escaped(escapedGroup, group.c_str()) << "', name='" Loading @@ -311,8 +313,8 @@ std::string webedit::Database::updateDocument(const std::string &ownerUid, << dbpp::SQL::escaped(escapedXml, xml.c_str()) << "', modified=CURRENT_TIMESTAMP WHERE id='" << dbpp::SQL::escaped(escapedId, id.c_str()) << "' AND owner_uid='" << dbpp::SQL::escaped(escapedUid, ownerUid.c_str()) << "';"; << "' AND domain='" << dbpp::SQL::escaped(escapedDomain, domain.c_str()) << "';"; _db->exec(sql, res); Loading Loading @@ -353,18 +355,18 @@ std::string webedit::Database::updateDocument(const std::string &ownerUid, return id; } bool webedit::Database::loadDocument(const std::string &ownerUid, bool webedit::Database::loadDocument(const std::string &domain, const std::string &id, std::string &name, std::string &xml, std::string &group) { dbpp::SQL sql; dbpp::DBResult res; std::vector<char> escapedId, escapedUid; std::vector<char> escapedId, escapedDomain; sql << "SELECT name, xml, group_name FROM documents WHERE id='" << dbpp::SQL::escaped(escapedId, id.c_str()) << "' AND owner_uid='" << dbpp::SQL::escaped(escapedUid, ownerUid.c_str()) << "';"; << "' AND domain='" << dbpp::SQL::escaped(escapedDomain, domain.c_str()) << "';"; int rows = _db->exec(sql, res); if (rows < 1) Loading @@ -376,17 +378,17 @@ bool webedit::Database::loadDocument(const std::string &ownerUid, return true; } bool webedit::Database::deleteDocument(const std::string &ownerUid, bool webedit::Database::deleteDocument(const std::string &domain, const std::string &id) { dbpp::SQL sql; dbpp::DBResult res; std::vector<char> escapedId, escapedUid; std::vector<char> escapedId, escapedDomain; // Verify ownership before deleting // Verify the document belongs to the caller's domain before deleting sql << "SELECT id FROM documents WHERE id='" << dbpp::SQL::escaped(escapedId, id.c_str()) << "' AND owner_uid='" << dbpp::SQL::escaped(escapedUid, ownerUid.c_str()) << "';"; << "' AND domain='" << dbpp::SQL::escaped(escapedDomain, domain.c_str()) << "';"; int rows = _db->exec(sql, res); if (rows < 1) Loading @@ -404,12 +406,12 @@ bool webedit::Database::deleteDocument(const std::string &ownerUid, sql.clear(); res.clear(); escapedId.clear(); escapedUid.clear(); escapedDomain.clear(); sql << "DELETE FROM documents WHERE id='" << dbpp::SQL::escaped(escapedId, id.c_str()) << "' AND owner_uid='" << dbpp::SQL::escaped(escapedUid, ownerUid.c_str()) << "';"; << "' AND domain='" << dbpp::SQL::escaped(escapedDomain, domain.c_str()) << "';"; _db->exec(sql, res); return true; Loading Loading @@ -443,48 +445,16 @@ std::string webedit::Database::listDocuments(const std::string &domain) { return result; } std::string webedit::Database::listDocumentsForOwnerDomain(const std::string &ownerUid, const std::string &domain) { dbpp::SQL sql; dbpp::DBResult res; std::vector<char> escapedUid, escapedDomain; sql << "SELECT id, name, created, modified, group_name FROM documents " << "WHERE owner_uid='" << dbpp::SQL::escaped(escapedUid, ownerUid.c_str()) << "' AND domain='" << dbpp::SQL::escaped(escapedDomain, domain.c_str()) << "' ORDER BY group_name, name, modified DESC;"; int rows = _db->exec(sql, res); json_object *arr = json_object_new_array(); for (int i = 0; i < rows; ++i) { json_object *obj = json_object_new_object(); json_object_object_add(obj, "id", json_object_new_string(res[i][0])); json_object_object_add(obj, "name", json_object_new_string(res[i][1])); json_object_object_add(obj, "created", json_object_new_string(res[i][2])); json_object_object_add(obj, "modified", json_object_new_string(res[i][3])); json_object_object_add(obj, "group", json_object_new_string(res[i][4])); json_object_array_add(arr, obj); } std::string result = json_object_to_json_string_ext(arr, JSON_C_TO_STRING_NOSLASHESCAPE); json_object_put(arr); return result; } bool webedit::Database::findDocumentIdByNameGroup(const std::string &ownerUid, const std::string &domain, bool webedit::Database::findDocumentIdByNameGroup(const std::string &domain, const std::string &name, const std::string &group, std::string &docId) { dbpp::SQL sql; dbpp::DBResult res; std::vector<char> escapedUid, escapedDomain, escapedName, escapedGroup; std::vector<char> escapedDomain, escapedName, escapedGroup; sql << "SELECT id FROM documents WHERE owner_uid='" << dbpp::SQL::escaped(escapedUid, ownerUid.c_str()) << "' AND domain='" << dbpp::SQL::escaped(escapedDomain, domain.c_str()) sql << "SELECT id FROM documents WHERE domain='" << dbpp::SQL::escaped(escapedDomain, domain.c_str()) << "' AND name='" << dbpp::SQL::escaped(escapedName, name.c_str()) << "' AND group_name='" << dbpp::SQL::escaped(escapedGroup, group.c_str()) << "' ORDER BY modified DESC LIMIT 1;"; Loading Loading @@ -545,14 +515,14 @@ bool webedit::Database::loadRevision(const std::string &revisionId, return true; } bool webedit::Database::restoreRevision(const std::string &ownerUid, bool webedit::Database::restoreRevision(const std::string &domain, const std::string &docId, const std::string &revisionId) { std::string name, xml; if (!loadRevision(revisionId, name, xml)) return false; updateDocument(ownerUid, docId, name, xml); updateDocument(domain, docId, name, xml); return true; } Loading Loading @@ -731,6 +701,7 @@ void webedit::Database::clearChatMessages(const std::string &ownerUid) { // --------------------------------------------------------------------------- std::string webedit::Database::saveSurvey(const std::string &ownerUid, const std::string &domain, const std::string &name, const std::string &title, const std::string &xml) { Loading @@ -739,11 +710,12 @@ std::string webedit::Database::saveSurvey(const std::string &ownerUid, dbpp::SQL sql; dbpp::DBResult res; std::vector<char> eOwner, eName, eTitle, eXml; std::vector<char> eOwner, eDomain, eName, eTitle, eXml; sql << "INSERT INTO survey_templates (id, owner_uid, name, title, xml) VALUES ('" sql << "INSERT INTO survey_templates (id, owner_uid, domain, name, title, xml) VALUES ('" << id.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(eTitle, title.c_str()) << "','" << dbpp::SQL::escaped(eXml, xml.c_str()) << "');"; Loading @@ -752,45 +724,45 @@ std::string webedit::Database::saveSurvey(const std::string &ownerUid, return std::string(id.c_str()); } bool webedit::Database::updateSurvey(const std::string &ownerUid, const std::string &id, bool webedit::Database::updateSurvey(const std::string &domain, const std::string &id, const std::string &name, const std::string &title, const std::string &xml) { dbpp::SQL sql; dbpp::DBResult res; std::vector<char> eOwner, eId, eName, eTitle, eXml; std::vector<char> eDomain, eId, eName, eTitle, eXml; sql << "UPDATE survey_templates SET name='" << dbpp::SQL::escaped(eName, name.c_str()) << "', title='" << dbpp::SQL::escaped(eTitle, title.c_str()) << "', xml='" << dbpp::SQL::escaped(eXml, xml.c_str()) << "', modified=CURRENT_TIMESTAMP 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; } bool webedit::Database::deleteSurvey(const std::string &ownerUid, const std::string &id) { bool webedit::Database::deleteSurvey(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 survey_templates 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::listSurveys(const std::string &ownerUid) { std::string webedit::Database::listSurveys(const std::string &domain) { dbpp::SQL sql; dbpp::DBResult res; std::vector<char> eOwner; std::vector<char> eDomain; sql << "SELECT id, name, title, created, modified " << "FROM survey_templates WHERE owner_uid='" << dbpp::SQL::escaped(eOwner, ownerUid.c_str()) << "FROM survey_templates WHERE domain='" << dbpp::SQL::escaped(eDomain, domain.c_str()) << "' ORDER BY name;"; int rows = _db->exec(sql, res); Loading @@ -810,13 +782,13 @@ std::string webedit::Database::listSurveys(const std::string &ownerUid) { return result; } std::string webedit::Database::listSurveyNames(const std::string &ownerUid) { std::string webedit::Database::listSurveyNames(const std::string &domain) { dbpp::SQL sql; dbpp::DBResult res; std::vector<char> eOwner; std::vector<char> eDomain; sql << "SELECT id, name FROM survey_templates WHERE owner_uid='" << dbpp::SQL::escaped(eOwner, ownerUid.c_str()) << "' ORDER BY name;"; sql << "SELECT id, name FROM survey_templates WHERE domain='" << dbpp::SQL::escaped(eDomain, domain.c_str()) << "' ORDER BY name;"; int rows = _db->exec(sql, res); json_object *arr = json_object_new_array(); Loading @@ -832,15 +804,15 @@ std::string webedit::Database::listSurveyNames(const std::string &ownerUid) { return result; } std::string webedit::Database::getSurvey(const std::string &ownerUid, const std::string &id) { std::string webedit::Database::getSurvey(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 << "SELECT id, name, title, xml, created, modified " << "FROM survey_templates 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 "{}"; Loading
editor/src/webedit_db.h +14 −16 File changed.Preview size limit exceeded, changes collapsed. Show changes