From ed62e9331bcc486c095974c5eaeed82bdbe107df Mon Sep 17 00:00:00 2001 From: vorotamoroz Date: Tue, 25 Oct 2022 11:33:37 +0900 Subject: [PATCH] Implemented: - A configuration information reporting tools has been implemented. Improved: - Fixed detection of IBM Cloudant --- src/LocalPouchDB.ts | 4 +- src/ObsidianLiveSyncSettingTab.ts | 96 +++++++++++++++++++++++-------- src/lib | 2 +- src/main.ts | 5 ++ 4 files changed, 80 insertions(+), 27 deletions(-) diff --git a/src/LocalPouchDB.ts b/src/LocalPouchDB.ts index 9040f88..89da019 100644 --- a/src/LocalPouchDB.ts +++ b/src/LocalPouchDB.ts @@ -5,7 +5,7 @@ import { Logger } from "./lib/src/logger.js"; import { PouchDB } from "./lib/src/pouchdb-browser.js"; import { EntryDoc, LOG_LEVEL } from "./lib/src/types.js"; import { enableEncryption } from "./lib/src/utils.js"; -import { isValidRemoteCouchDBURI } from "./lib/src/utils_couchdb.js"; +import { isCloudantURI, isValidRemoteCouchDBURI } from "./lib/src/utils_couchdb.js"; import { id2path, path2id } from "./utils.js"; export class LocalPouchDB extends LocalPouchDBBase { @@ -77,7 +77,7 @@ export class LocalPouchDB extends LocalPouchDBBase { const opts_length = opts.body.toString().length; if (opts_length > 1024 * 1024 * 10) { // over 10MB - if (uri.contains(".cloudantnosqldb.")) { + if (isCloudantURI(uri)) { this.last_successful_post = false; Logger("This request should fail on IBM Cloudant.", LOG_LEVEL.VERBOSE); throw new Error("This request should fail on IBM Cloudant."); diff --git a/src/ObsidianLiveSyncSettingTab.ts b/src/ObsidianLiveSyncSettingTab.ts index 9ce4a9a..b56d147 100644 --- a/src/ObsidianLiveSyncSettingTab.ts +++ b/src/ObsidianLiveSyncSettingTab.ts @@ -1,12 +1,29 @@ -import { App, PluginSettingTab, Setting, sanitizeHTMLToDom, RequestUrlParam, requestUrl, TextAreaComponent, MarkdownRenderer } from "obsidian"; -import { DEFAULT_SETTINGS, LOG_LEVEL, RemoteDBSettings } from "./lib/src/types"; +import { App, PluginSettingTab, Setting, sanitizeHTMLToDom, RequestUrlParam, requestUrl, TextAreaComponent, MarkdownRenderer, stringifyYaml } from "obsidian"; +import { DEFAULT_SETTINGS, LOG_LEVEL, ObsidianLiveSyncSettings, RemoteDBSettings } from "./lib/src/types"; import { path2id, id2path } from "./utils"; import { delay, versionNumberString2Number } from "./lib/src/utils"; import { Logger } from "./lib/src/logger"; -import { checkSyncInfo } from "./lib/src/utils_couchdb.js"; +import { checkSyncInfo, isCloudantURI } from "./lib/src/utils_couchdb.js"; import { testCrypt } from "./lib/src/e2ee_v2"; import ObsidianLiveSyncPlugin from "./main"; +const requestToCouchDB = async (baseUri: string, username: string, password: string, origin: string, key?: string, body?: string) => { + const utf8str = String.fromCharCode.apply(null, new TextEncoder().encode(`${username}:${password}`)); + const encoded = window.btoa(utf8str); + const authHeader = "Basic " + encoded; + // const origin = "capacitor://localhost"; + const transformedHeaders: Record = { authorization: authHeader, origin: origin }; + const uri = `${baseUri}/_node/_local/_config${key ? "/" + key : ""}`; + + const requestParam: RequestUrlParam = { + url: uri, + method: body ? "PUT" : "GET", + headers: transformedHeaders, + contentType: "application/json", + body: body ? JSON.stringify(body) : undefined, + }; + return await requestUrl(requestParam); +}; export class ObsidianLiveSyncSettingTab extends PluginSettingTab { plugin: ObsidianLiveSyncPlugin; @@ -474,23 +491,10 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab { .onClick(async () => { const checkConfig = async () => { try { - const requestToCouchDB = async (baseUri: string, username: string, password: string, origin: string, key?: string, body?: string) => { - const utf8str = String.fromCharCode.apply(null, new TextEncoder().encode(`${username}:${password}`)); - const encoded = window.btoa(utf8str); - const authHeader = "Basic " + encoded; - // const origin = "capacitor://localhost"; - const transformedHeaders: Record = { authorization: authHeader, origin: origin }; - const uri = `${baseUri}/_node/_local/_config${key ? "/" + key : ""}`; - - const requestParam: RequestUrlParam = { - url: uri, - method: body ? "PUT" : "GET", - headers: transformedHeaders, - contentType: "application/json", - body: body ? JSON.stringify(body) : undefined, - }; - return await requestUrl(requestParam); - }; + if (isCloudantURI(this.plugin.settings.couchDB_URI)) { + Logger("This feature cannot be used with IBM Cloudant.", LOG_LEVEL.NOTICE); + return; + } const r = await requestToCouchDB(this.plugin.settings.couchDB_URI, this.plugin.settings.couchDB_USER, this.plugin.settings.couchDB_PASSWORD, window.origin); @@ -573,7 +577,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab { addResult("βœ” httpd.enable_cors is ok."); } // If the server is not cloudant, configure request size - if (!this.plugin.settings.couchDB_URI.contains(".cloudantnosqldb.")) { + if (!isCloudantURI(this.plugin.settings.couchDB_URI)) { // REQUEST SIZE if (Number(responseConfig?.chttpd?.max_http_request_size ?? 0) < 4294967296) { addResult("❗ chttpd.max_http_request_size is low)"); @@ -637,7 +641,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab { addResult("--Done--", ["ob-btn-config-head"]); addResult("If you have some trouble with Connection-check even though all Config-check has been passed, Please check your reverse proxy's configuration.", ["ob-btn-config-info"]); } catch (ex) { - Logger(`Checking configuration failed`); + Logger(`Checking configuration failed`, LOG_LEVEL.NOTICE); Logger(ex); } }; @@ -675,7 +679,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab { if (!this.plugin.settings.encrypt) { this.plugin.settings.passphrase = ""; } - if (this.plugin.settings.couchDB_URI.contains(".cloudantnosqldb.")) { + if (isCloudantURI(this.plugin.settings.couchDB_URI)) { this.plugin.settings.customChunkSize = 0; } else { this.plugin.settings.customChunkSize = 100; @@ -696,7 +700,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab { if (!this.plugin.settings.encrypt) { this.plugin.settings.passphrase = ""; } - if (this.plugin.settings.couchDB_URI.contains(".cloudantnosqldb.")) { + if (isCloudantURI(this.plugin.settings.couchDB_URI)) { this.plugin.settings.customChunkSize = 0; } else { this.plugin.settings.customChunkSize = 100; @@ -1263,6 +1267,50 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab { containerHatchEl.createEl("h3", { text: "Hatch" }); + + new Setting(containerHatchEl) + .setName("Make report to inform the issue") + .setDesc("Verify and repair all files and update database without restoring") + .addButton((button) => + button + .setButtonText("Make report") + .setDisabled(false) + .onClick(async () => { + let responseConfig: any = {}; + const REDACTED = "𝑅𝐸𝐷𝐴𝐢𝑇𝐸𝐷"; + try { + const r = await requestToCouchDB(this.plugin.settings.couchDB_URI, this.plugin.settings.couchDB_USER, this.plugin.settings.couchDB_PASSWORD, window.origin); + + Logger(JSON.stringify(r.json, null, 2)); + + responseConfig = r.json; + responseConfig["couch_httpd_auth"].secret = REDACTED; + responseConfig["couch_httpd_auth"].authentication_db = REDACTED; + responseConfig["couch_httpd_auth"].authentication_redirect = REDACTED; + responseConfig["couchdb"].uuid = REDACTED; + responseConfig["admins"] = REDACTED; + + } catch (ex) { + responseConfig = "Requesting information to the remote CouchDB has been failed. If you are using IBM Cloudant, it is the normal behaviour." + } + const pluginConfig = JSON.parse(JSON.stringify(this.plugin.settings)) as ObsidianLiveSyncSettings; + pluginConfig.couchDB_DBNAME = REDACTED; + pluginConfig.couchDB_PASSWORD = REDACTED; + pluginConfig.couchDB_URI = isCloudantURI(pluginConfig.couchDB_URI) ? "cloudant" : "self-hosted"; + pluginConfig.couchDB_USER = REDACTED; + pluginConfig.passphrase = REDACTED; + pluginConfig.workingPassphrase = REDACTED; + + const msgConfig = `----remote config---- +${stringifyYaml(responseConfig)} +---- Plug-in config --- +${stringifyYaml(pluginConfig)}`; + console.log(msgConfig); + await navigator.clipboard.writeText(msgConfig); + Logger(`Information has been copied to clipboard`, LOG_LEVEL.NOTICE); + }) + ); + if (this.plugin.localDatabase.remoteLockedAndDeviceNotAccepted) { const c = containerHatchEl.createEl("div", { text: "To prevent unwanted vault corruption, the remote database has been locked for synchronization, and this device was not marked as 'resolved'. it caused by some operations like this. re-initialized. Local database initialization should be required. please back your vault up, reset local database, and press 'Mark this device as resolved'. ", diff --git a/src/lib b/src/lib index 8d9f82e..d73b96b 160000 --- a/src/lib +++ b/src/lib @@ -1 +1 @@ -Subproject commit 8d9f82ed9bcf1a999b5edb6d9be6f84fcceb6c89 +Subproject commit d73b96ba2a437e1dd0756d0cdf4cb684c28aa5ab diff --git a/src/main.ts b/src/main.ts index 34683cc..80192d5 100644 --- a/src/main.ts +++ b/src/main.ts @@ -35,6 +35,7 @@ import { decrypt, encrypt } from "./lib/src/e2ee_v2"; const isDebug = false; import { InputStringDialog, PluginDialogModal, PopoverSelectString } from "./dialogs"; +import { isCloudantURI } from "./lib/src/utils_couchdb"; setNoticeClass(Notice); @@ -697,6 +698,10 @@ export default class ObsidianLiveSyncPlugin extends Plugin { this.settings.deviceAndVaultName = ""; } } + if (isCloudantURI(this.settings.couchDB_URI) && this.settings.customChunkSize != 0) { + Logger("Configuration verification founds problems with your configuration. This has been fixed automatically. But you may already have data that cannot be synchronised. If this is the case, please rebuild everything.", LOG_LEVEL.NOTICE) + this.settings.customChunkSize = 0; + } this.deviceAndVaultName = localStorage.getItem(lsKey) || ""; }