Implemented:

- Encrypting setup URI by passphrse.
(Note: You have to make the setup URI again)

Fixed:
- Setup procedure fixed.
- Status text fixed.
- Documentation fixed.
This commit is contained in:
vorotamoroz
2022-06-19 15:36:36 +09:00
parent 4634ab73b1
commit 3e76292aa7
7 changed files with 149 additions and 28 deletions

View File

@@ -188,7 +188,7 @@ export class ObsidianLiveSyncSettingTab extends PluginSettingTab {
);
new Setting(containerRemoteDatabaseEl)
.setName("End to End Encryption")
.setDesc("Encrypting contents on the remote database. If you use the plugins synchronizing feature, enabling this is recommend.")
.setDesc("Encrypt contents on the remote database. If you use the plugins synchronizing feature, enabling this is recommend.")
.addToggle((toggle) =>
toggle.setValue(this.plugin.settings.workingEncrypt).onChange(async (value) => {
this.plugin.settings.workingEncrypt = value;

View File

@@ -1,4 +1,4 @@
import { debounce, Notice, Plugin, TFile, addIcon, TFolder, normalizePath, TAbstractFile, Editor, MarkdownView, PluginManifest, Modal, App, FuzzySuggestModal } from "obsidian";
import { debounce, Notice, Plugin, TFile, addIcon, TFolder, normalizePath, TAbstractFile, Editor, MarkdownView, PluginManifest, Modal, App, FuzzySuggestModal, Setting } from "obsidian";
import { diff_match_patch } from "diff-match-patch";
import { EntryDoc, LoadedEntry, ObsidianLiveSyncSettings, diff_check_result, diff_result_leaf, EntryBody, LOG_LEVEL, VER, DEFAULT_SETTINGS, diff_result, FLAGMD_REDFLAG, SYNCINFO_ID } from "./lib/src/types";
@@ -59,6 +59,62 @@ class PluginDialogModal extends Modal {
}
}
}
class InputStringDialog extends Modal {
result: string | false = false;
onSubmit: (result: string | boolean) => void;
title: string;
key: string;
placeholder: string;
isManuallyClosed = false;
constructor(app: App, title: string, key: string, placeholder: string, onSubmit: (result: string | false) => void) {
super(app);
this.onSubmit = onSubmit;
this.title = title;
this.placeholder = placeholder;
this.key = key;
}
onOpen() {
const { contentEl } = this;
contentEl.createEl("h1", { text: this.title });
new Setting(contentEl).setName(this.key).addText((text) =>
text.onChange((value) => {
this.result = value;
})
);
new Setting(contentEl).addButton((btn) =>
btn
.setButtonText("Ok")
.setCta()
.onClick(() => {
this.isManuallyClosed = true;
this.close();
})
).addButton((btn) =>
btn
.setButtonText("Cancel")
.setCta()
.onClick(() => {
this.close();
})
);
}
onClose() {
const { contentEl } = this;
contentEl.empty();
if (this.isManuallyClosed) {
this.onSubmit(this.result);
} else {
this.onSubmit(false);
}
}
}
class PopoverYesNo extends FuzzySuggestModal<string> {
app: App;
callback: (e: string) => void = () => { };
@@ -99,6 +155,13 @@ const askYesNo = (app: App, message: string): Promise<"yes" | "no"> => {
});
};
const askString = (app: App, title: string, key: string, placeholder: string): Promise<string | false> => {
return new Promise((res) => {
const dialog = new InputStringDialog(app, title, key, placeholder, (result) => res(result));
dialog.open();
});
};
export default class ObsidianLiveSyncPlugin extends Plugin {
settings: ObsidianLiveSyncSettings;
localDatabase: LocalPouchDB;
@@ -241,20 +304,40 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
Logger(ex, LOG_LEVEL.VERBOSE);
}
});
const configURIBase = "obsidian://setuplivesync?settings=";
this.addCommand({
id: "livesync-exportconfig",
name: "Copy setup uri (beta)",
id: "livesync-copysetupuri",
name: "Copy setup URI (beta)",
callback: async () => {
const encryptedSetting = encodeURIComponent(await encrypt(JSON.stringify(this.settings), "---"));
const uri = `obsidian://setuplivesync?settings=${encryptedSetting}`;
const encryptingPassphrase = await askString(this.app, "Encrypt your settings", "Passphrase", "");
if (encryptingPassphrase === false) return;
const encryptedSetting = encodeURIComponent(await encrypt(JSON.stringify(this.settings), encryptingPassphrase));
const uri = `${configURIBase}${encryptedSetting}`;
await navigator.clipboard.writeText(uri);
Logger("Setup uri copied to clipboard", LOG_LEVEL.NOTICE);
Logger("Setup URI copied to clipboard", LOG_LEVEL.NOTICE);
},
});
this.registerObsidianProtocolHandler("setuplivesync", async (conf: any) => {
this.addCommand({
id: "livesync-opensetupuri",
name: "Open setup URI (beta)",
callback: async () => {
const setupURI = await askString(this.app, "Set up manually", "Set up URI", `${configURIBase}aaaaa`);
if (setupURI === false) return;
if (!setupURI.startsWith(`${configURIBase}`)) {
Logger("Set up URI looks wrong.", LOG_LEVEL.NOTICE);
return;
}
const config = decodeURIComponent(setupURI.substring(configURIBase.length));
console.dir(config)
await setupwizard(config);
},
});
const setupwizard = async (confString: string) => {
try {
const oldConf = JSON.parse(JSON.stringify(this.settings));
const newconf = await JSON.parse(await decrypt(conf.settings, "---"));
const encryptingPassphrase = await askString(this.app, "Passphrase", "Passphrase for your settings", "");
if (encryptingPassphrase === false) return;
const newconf = await JSON.parse(await decrypt(confString, encryptingPassphrase));
if (newconf) {
const result = await askYesNo(this.app, "Importing LiveSync's conf, OK?");
if (result == "yes") {
@@ -269,6 +352,11 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
// nothing to do. so peaceful.
this.settings = newSettingW;
await this.saveSettings();
const replicate = await askYesNo(this.app, "Unlock and replicate?");
if (replicate == "yes") {
await this.replicate(true);
await this.markRemoteUnlocked();
}
Logger("Configuration loaded.", LOG_LEVEL.NOTICE);
return;
}
@@ -313,8 +401,11 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
Logger("Cancelled.", LOG_LEVEL.NOTICE);
}
} catch (ex) {
Logger("Couldn't parse configuration uri.", LOG_LEVEL.NOTICE);
Logger("Couldn't parse or decrypt configuration uri.", LOG_LEVEL.NOTICE);
}
};
this.registerObsidianProtocolHandler("setuplivesync", async (conf: any) => {
await setupwizard(conf.settings);
});
this.addCommand({
id: "livesync-replicate",
@@ -1217,14 +1308,14 @@ export default class ObsidianLiveSyncPlugin extends Plugin {
const locks = getLocks();
const pendingTask = locks.pending.length
? "\nPending: " +
Object.entries([...new Set([...locks.pending])].reduce((p, c) => ({ ...p, [c]: p[c] ?? 0 + 1 }), {} as { [key: string]: number }))
Object.entries(locks.pending.reduce((p, c) => ({ ...p, [c]: (p[c] ?? 0) + 1 }), {} as { [key: string]: number }))
.map((e) => `${e[0]}${e[1] == 1 ? "" : `(${e[1]})`}`)
.join(", ")
: "";
const runningTask = locks.running.length
? "\nRunning: " +
Object.entries([...new Set([...locks.running])].reduce((p, c) => ({ ...p, [c]: p[c] ?? 0 + 1 }), {} as { [key: string]: number }))
Object.entries(locks.running.reduce((p, c) => ({ ...p, [c]: (p[c] ?? 0) + 1 }), {} as { [key: string]: number }))
.map((e) => `${e[0]}${e[1] == 1 ? "" : `(${e[1]})`}`)
.join(", ")
: "";