From f26ee8bbc5b98cec2fe21216cb959785a0299e7b Mon Sep 17 00:00:00 2001 From: fyears Date: Sat, 1 Jan 2022 13:55:27 +0800 Subject: [PATCH] optimize dropbox flow --- src/baseTypes.ts | 1 + src/main.ts | 96 ++++++++++++++++++++++++++++++++++++++--- src/remoteForDropbox.ts | 9 +++- src/settings.ts | 79 ++++++--------------------------- 4 files changed, 111 insertions(+), 74 deletions(-) diff --git a/src/baseTypes.ts b/src/baseTypes.ts index 444a9cb..99099f1 100644 --- a/src/baseTypes.ts +++ b/src/baseTypes.ts @@ -63,6 +63,7 @@ export interface RemoteItem { export const COMMAND_URI = "remotely-save"; export const COMMAND_CALLBACK = "remotely-save-cb"; export const COMMAND_CALLBACK_ONEDRIVE = "remotely-save-cb-onedrive"; +export const COMMAND_CALLBACK_DROPBOX = "remotely-save-cb-dropbox"; export interface UriParams { func?: string; diff --git a/src/main.ts b/src/main.ts index 7a0868f..d7b3f56 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,6 +1,11 @@ import { Modal, Notice, Plugin, Setting } from "obsidian"; import type { RemotelySavePluginSettings } from "./baseTypes"; -import { COMMAND_CALLBACK, COMMAND_URI } from "./baseTypes"; +import { + COMMAND_CALLBACK, + COMMAND_CALLBACK_ONEDRIVE, + COMMAND_CALLBACK_DROPBOX, + COMMAND_URI, +} from "./baseTypes"; import { importQrCodeUri } from "./importExport"; import type { InternalDBs } from "./localdb"; import { @@ -11,7 +16,12 @@ import { prepareDBs, } from "./localdb"; import { RemoteClient } from "./remote"; -import { DEFAULT_DROPBOX_CONFIG } from "./remoteForDropbox"; +import { + DEFAULT_DROPBOX_CONFIG, + getAuthUrlAndVerifier as getAuthUrlAndVerifierDropbox, + sendAuthReq as sendAuthReqDropbox, + setConfigBySuccessfullAuthInplace, +} from "./remoteForDropbox"; import { AccessCodeResponseSuccessfulType, DEFAULT_ONEDRIVE_CONFIG, @@ -101,8 +111,84 @@ export default class RemotelySavePlugin extends Plugin { ); } ); + this.registerObsidianProtocolHandler( - "remotely-save-cb-onedrive", + COMMAND_CALLBACK_DROPBOX, + async (inputParams) => { + if (inputParams.code !== undefined) { + if (this.oauth2Info.helperModal !== undefined) { + this.oauth2Info.helperModal.contentEl.empty(); + this.oauth2Info.helperModal.contentEl.createEl("p", { + text: "Connecting to Dropbox...", + }); + this.oauth2Info.helperModal.contentEl.createEl("p", { + text: "Please DO NOT close this modal.", + }); + } + + let authRes = await sendAuthReqDropbox( + this.settings.dropbox.clientID, + this.oauth2Info.verifier, + inputParams.code + ); + + const self = this; + setConfigBySuccessfullAuthInplace( + this.settings.dropbox, + authRes, + () => self.saveSettings() + ); + + const client = new RemoteClient( + "dropbox", + undefined, + undefined, + this.settings.dropbox, + undefined, + this.app.vault.getName(), + () => self.saveSettings() + ); + + const username = await client.getUser(); + this.settings.dropbox.username = username; + await this.saveSettings(); + + new Notice(`Good! We've connected to Dropbox as user ${username}!`); + + this.oauth2Info.verifier = ""; // reset it + this.oauth2Info.helperModal?.close(); // close it + this.oauth2Info.helperModal = undefined; + + this.oauth2Info.authDiv?.toggleClass( + "dropbox-auth-button-hide", + this.settings.dropbox.username !== "" + ); + this.oauth2Info.authDiv = undefined; + + this.oauth2Info.revokeAuthSetting?.setDesc( + `You've connected as user ${this.settings.dropbox.username}. If you want to disconnect, click this button.` + ); + this.oauth2Info.revokeAuthSetting = undefined; + this.oauth2Info.revokeDiv?.toggleClass( + "dropbox-revoke-auth-button-hide", + this.settings.dropbox.username === "" + ); + this.oauth2Info.revokeDiv = undefined; + } else { + new Notice( + "Something went wrong from response from Dropbox. Maybe you rejected the auth?" + ); + throw Error( + `do not know how to deal with the callback: ${JSON.stringify( + inputParams + )}` + ); + } + } + ); + + this.registerObsidianProtocolHandler( + COMMAND_CALLBACK_ONEDRIVE, async (inputParams) => { if (inputParams.code !== undefined) { if (this.oauth2Info.helperModal !== undefined) { @@ -132,7 +218,7 @@ export default class RemotelySavePlugin extends Plugin { Date.now() + rsp.expires_in - 5 * 60 * 1000; this.settings.onedrive.accessTokenExpiresInSeconds = rsp.expires_in; this.settings.onedrive.refreshToken = rsp.refresh_token; - this.saveSettings(); + await this.saveSettings(); const self = this; const client = new RemoteClient( @@ -145,7 +231,7 @@ export default class RemotelySavePlugin extends Plugin { () => self.saveSettings() ); this.settings.onedrive.username = await client.getUser(); - this.saveSettings(); + await this.saveSettings(); this.oauth2Info.verifier = ""; // reset it this.oauth2Info.helperModal?.close(); // close it diff --git a/src/remoteForDropbox.ts b/src/remoteForDropbox.ts index 18c1f53..858e971 100644 --- a/src/remoteForDropbox.ts +++ b/src/remoteForDropbox.ts @@ -1,7 +1,11 @@ import { Dropbox, DropboxAuth, files } from "dropbox"; import { Vault } from "obsidian"; import * as path from "path"; -import { DropboxConfig, RemoteItem } from "./baseTypes"; +import { + DropboxConfig, + RemoteItem, + COMMAND_CALLBACK_DROPBOX, +} from "./baseTypes"; import { decryptArrayBuffer, encryptArrayBuffer } from "./encrypt"; import { bufferToArrayBuffer, getFolderLevels, mkdirpInVault } from "./misc"; @@ -153,7 +157,7 @@ export const getAuthUrlAndVerifier = async (appKey: string) => { }); const authUrl = ( await auth.getAuthenticationUrl( - undefined, + `obsidian://${COMMAND_CALLBACK_DROPBOX}`, undefined, "code", "offline", @@ -191,6 +195,7 @@ export const sendAuthReq = async ( grant_type: "authorization_code", code_verifier: verifier, client_id: appKey, + redirect_uri: `obsidian://${COMMAND_CALLBACK_DROPBOX}`, }), }); const resp2 = (await resp1.json()) as DropboxSuccessAuthRes; diff --git a/src/settings.ts b/src/settings.ts index 2e734a2..9129fef 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -105,78 +105,18 @@ class DropboxAuthModal extends Modal { const { authUrl, verifier } = await getAuthUrlAndVerifierDropbox( this.plugin.settings.dropbox.clientID ); + this.plugin.oauth2Info.verifier = verifier; contentEl.createEl("p", { - text: "Step 1: Visit the address in a browser, and follow the steps.", + text: "Visit the address in a browser, and follow the steps.", + }); + contentEl.createEl("p", { + text: "Finally you should be redirected to Obsidian.", }); contentEl.createEl("p").createEl("a", { href: authUrl, text: authUrl, }); - - contentEl.createEl("p", { - text: 'Step 2: In the end of the web flow, you obtain a long code. Paste it here then click "Submit".', - }); - - let authCode = ""; - new Setting(contentEl) - .setName("Auth Code from web page") - .setDesc('You need to click "Confirm".') - .addText((text) => - text - .setPlaceholder("") - .setValue("") - .onChange((val) => { - authCode = val.trim(); - }) - ) - .addButton(async (button) => { - button.setButtonText("Confirm"); - button.onClick(async () => { - new Notice("Trying to connect to Dropbox"); - try { - const authRes = await sendAuthReqDropbox( - this.plugin.settings.dropbox.clientID, - verifier, - authCode - ); - const self = this; - setConfigBySuccessfullAuthInplace( - this.plugin.settings.dropbox, - authRes, - () => self.plugin.saveSettings() - ); - const client = new RemoteClient( - "dropbox", - undefined, - undefined, - this.plugin.settings.dropbox, - undefined, - this.app.vault.getName(), - () => self.plugin.saveSettings() - ); - const username = await client.getUser(); - this.plugin.settings.dropbox.username = username; - await this.plugin.saveSettings(); - new Notice(`Good! We've connected to Dropbox as user ${username}!`); - this.authDiv.toggleClass( - "dropbox-auth-button-hide", - this.plugin.settings.dropbox.username !== "" - ); - this.revokeAuthDiv.toggleClass( - "dropbox-revoke-auth-button-hide", - this.plugin.settings.dropbox.username === "" - ); - this.revokeAuthSetting.setDesc( - `You've connected as user ${this.plugin.settings.dropbox.username}. If you want to disconnect, click this button.` - ); - this.close(); - } catch (err) { - console.error(err); - new Notice("Something goes wrong while connecting to Dropbox."); - } - }); - }); } onClose() { @@ -541,13 +481,18 @@ export class RemotelySaveSettingTab extends PluginSettingTab { .addButton(async (button) => { button.setButtonText("Auth"); button.onClick(async () => { - new DropboxAuthModal( + const modal = new DropboxAuthModal( this.app, this.plugin, dropboxAuthDiv, dropboxRevokeAuthDiv, dropboxRevokeAuthSetting - ).open(); + ); + this.plugin.oauth2Info.helperModal = modal; + this.plugin.oauth2Info.authDiv = dropboxAuthDiv; + this.plugin.oauth2Info.revokeDiv = dropboxRevokeAuthDiv; + this.plugin.oauth2Info.revokeAuthSetting = dropboxRevokeAuthSetting; + modal.open(); }); });