From eb2611dd833003572ffa5dc20c302d7d339506e9 Mon Sep 17 00:00:00 2001 From: Saurabh Date: Mon, 19 Jun 2017 17:37:19 +0530 Subject: [PATCH 1/4] [enhance] update dropbox backup to be compatible with Dropbox V2 api --- .../dropbox_settings/dropbox_settings.js | 7 +- .../dropbox_settings/dropbox_settings.json | 41 ++- .../dropbox_settings/dropbox_settings.py | 272 ++++++++---------- 3 files changed, 158 insertions(+), 162 deletions(-) diff --git a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.js b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.js index a9cdeca66a..8b4215baac 100644 --- a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.js +++ b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.js @@ -14,10 +14,7 @@ frappe.ui.form.on('Dropbox Settings', { freeze: true, callback: function(r) { if(!r.exc) { - frm.set_value('dropbox_access_key', r.message.dropbox_access_key) - frm.set_value('dropbox_access_secret', r.message.dropbox_access_secret) - frm.save() - window.open(r.message.url); + window.open(r.message.auth_url); } } }) @@ -29,7 +26,7 @@ frappe.ui.form.on('Dropbox Settings', { take_backup: function(frm) { if ((frm.doc.app_access_key && frm.doc.app_secret_key) || frm.doc.dropbox_setup_via_site_config){ - if (frm.doc.dropbox_access_key && frm.doc.dropbox_access_secret) { + if (frm.doc.dropbox_access_token) { frm.add_custom_button(__("Take Backup Now"), function(frm){ frappe.call({ method: "frappe.integrations.doctype.dropbox_settings.dropbox_settings.take_backup", diff --git a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.json b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.json index d4901632b2..5e0e6dc508 100644 --- a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.json +++ b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.json @@ -12,6 +12,7 @@ "editable_grid": 1, "fields": [ { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -41,6 +42,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -70,6 +72,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -100,6 +103,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -130,6 +134,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -160,6 +165,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -189,6 +195,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -218,6 +225,7 @@ "unique": 0 }, { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -247,6 +255,37 @@ "unique": 0 }, { + "allow_bulk_edit": 0, + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "columns": 0, + "fieldname": "dropbox_access_token", + "fieldtype": "Password", + "hidden": 0, + "ignore_user_permissions": 0, + "ignore_xss_filter": 0, + "in_filter": 0, + "in_global_search": 0, + "in_list_view": 0, + "in_standard_filter": 0, + "label": "Dropbox Access Token", + "length": 0, + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "print_hide_if_no_value": 0, + "read_only": 0, + "remember_last_selected_value": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_bulk_edit": 0, "allow_on_submit": 0, "bold": 0, "collapsible": 0, @@ -286,7 +325,7 @@ "issingle": 1, "istable": 0, "max_attachments": 0, - "modified": "2017-03-08 17:25:45.564492", + "modified": "2017-06-19 04:02:22.472465", "modified_by": "Administrator", "module": "Integrations", "name": "Dropbox Settings", diff --git a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py index 3461afbbf9..479b8189e4 100644 --- a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py +++ b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py @@ -6,11 +6,12 @@ from __future__ import unicode_literals import frappe import os from frappe import _ +from frappe.model.document import Document +import dropbox from frappe.utils.backups import new_backup from frappe.utils.background_jobs import enqueue from frappe.utils import (cint, split_emails, get_request_site_address, cstr, get_files_path, get_backups_path, encode) -from frappe.model.document import Document ignore_list = [".DS_Store"] @@ -19,92 +20,10 @@ class DropboxSettings(Document): if not self.app_access_key and frappe.conf.dropbox_access_key: self.dropbox_setup_via_site_config = 1 - def validate(self): - if not self.flags.ignore_mandatory: - self.validate_dropbox_credentails() - - def validate_dropbox_credentails(self): - try: - self.get_dropbox_session() - except Exception as e: - frappe.throw(e.message) - - def get_dropbox_session(self): - try: - from dropbox import session - except: - raise Exception(_("Please install dropbox python module")) - - app_access_key = self.app_access_key or frappe.conf.dropbox_access_key - app_secret_key = self.get_password(fieldname="app_secret_key", - raise_exception=False) if self.app_secret_key else frappe.conf.dropbox_secret_key - - if not (app_access_key or app_secret_key): - raise Exception(_("Please set Dropbox access keys in your site config")) - - sess = session.DropboxSession(app_access_key, app_secret_key, "app_folder") - - return sess - -#get auth token -@frappe.whitelist() -def get_dropbox_authorize_url(): - doc = frappe.get_doc("Dropbox Settings") - sess = doc.get_dropbox_session() - request_token = sess.obtain_request_token() - - doc.update({ - "dropbox_access_key": request_token.key, - "dropbox_access_secret": request_token.secret - }) - - return_address = get_request_site_address(True) \ - + "?cmd=frappe.integrations.doctype.dropbox_settings.dropbox_settings.dropbox_callback" - - url = sess.build_authorize_url(request_token, return_address) - - return { - "url": url, - "dropbox_access_key": request_token.key, - "dropbox_access_secret": request_token.secret - } - -@frappe.whitelist(allow_guest=True) -def dropbox_callback(oauth_token=None, not_approved=False): - doc = frappe.get_doc("Dropbox Settings") - close = '

' + _('Please close this window') + '

' - - if not not_approved: - if doc.get_password(fieldname="dropbox_access_key", raise_exception=False)==oauth_token: - sess = doc.get_dropbox_session() - sess.set_request_token(doc.get_password(fieldname="dropbox_access_key", raise_exception=False), - doc.get_password(fieldname="dropbox_access_secret", raise_exception=False)) - - access_token = sess.obtain_access_token() - - frappe.db.set_value("Dropbox Settings", None, "dropbox_access_key", access_token.key) - frappe.db.set_value("Dropbox Settings", None, "dropbox_access_secret", access_token.secret) - - frappe.db.commit() - else: - frappe.respond_as_web_page(_("Dropbox Setup"), - _("Illegal Access Token. Please try again") + close, - indicator_color='red', - http_status_code=frappe.AuthenticationError.http_status_code) - else: - frappe.respond_as_web_page(_("Dropbox Setup"), - _("You did not apporve Dropbox Access.") + close, - indicator_color='red') - - frappe.respond_as_web_page(_("Dropbox Setup"), - _("Dropbox access is approved!") + close, - indicator_color='red') - -# backup process @frappe.whitelist() def take_backup(): "Enqueue longjob for taking backup to dropbox" - enqueue("frappe.integrations.doctype.dropbox_settings.dropbox_settings.take_backup_to_dropbox", queue='long') + enqueue("frappe.integrations.doctype.dropbox_settings.dropbox_settings.take_backup_to_dropbox", queue='long', timeout=1500) frappe.msgprint(_("Queued for backup. It may take a few minutes to an hour.")) def take_backups_daily(): @@ -158,92 +77,38 @@ def backup_to_dropbox(): if not frappe.db: frappe.connect() - dropbox_client = get_dropbox_client() # upload database + dropbox_settings = get_dropbox_settings() + if not dropbox_settings['access_token']: + return + + dropbox_client = dropbox.Dropbox(dropbox_settings['access_token']) backup = new_backup(ignore_files=True) filename = os.path.join(get_backups_path(), os.path.basename(backup.backup_path_db)) - dropbox_client = upload_file_to_dropbox(filename, "/database", dropbox_client) + upload_file_to_dropbox(filename, "/database", dropbox_client) frappe.db.close() - + # upload files to files folder did_not_upload = [] error_log = [] - dropbox_client = upload_from_folder(get_files_path(), "/files", dropbox_client, did_not_upload, error_log) - dropbox_client = upload_from_folder(get_files_path(is_private=1), "/private/files", dropbox_client, did_not_upload, error_log) + upload_from_folder(get_files_path(), "/files", dropbox_client, did_not_upload, error_log) + upload_from_folder(get_files_path(is_private=1), "/private/files", dropbox_client, did_not_upload, error_log) frappe.connect() - return did_not_upload, list(set(error_log)) -def get_dropbox_client(previous_dropbox_client=None): - from dropbox import client - doc = frappe.get_doc("Dropbox Settings") - sess = doc.get_dropbox_session() - - sess.set_token(doc.get_password(fieldname="dropbox_access_key", raise_exception=False), - doc.get_password(fieldname="dropbox_access_secret", raise_exception=False)) - - dropbox_client = client.DropboxClient(sess) - - # upgrade to oauth2 - token = dropbox_client.create_oauth2_access_token() - dropbox_client = client.DropboxClient(token) - if previous_dropbox_client: - dropbox_client.connection_reset_count = previous_dropbox_client.connection_reset_count + 1 - else: - dropbox_client.connection_reset_count = 0 - return dropbox_client - -def upload_file_to_dropbox(filename, folder, dropbox_client): - from dropbox import rest - size = os.stat(encode(filename)).st_size - - with open(encode(filename), 'r') as f: - # if max packet size reached, use chunked uploader - max_packet_size = 4194304 - - if size > max_packet_size: - uploader = dropbox_client.get_chunked_uploader(f, size) - while uploader.offset < size: - try: - uploader.upload_chunked() - uploader.finish(folder + "/" + os.path.basename(filename), overwrite=True) - - except rest.ErrorResponse as e: - # if "[401] u'Access token not found.'", - # it means that the user needs to again allow dropbox backup from the UI - # so re-raise - exc_message = cstr(e) - if (exc_message.startswith("[401]") - and dropbox_client.connection_reset_count < 10 - and exc_message != "[401] u'Access token not found.'"): - - - # session expired, so get a new connection! - # [401] u"The given OAuth 2 access token doesn't exist or has expired." - dropbox_client = get_dropbox_client(dropbox_client) - - else: - raise - else: - dropbox_client.put_file(folder + "/" + os.path.basename(filename), f, overwrite=True) - - return dropbox_client - def upload_from_folder(path, dropbox_folder, dropbox_client, did_not_upload, error_log): - import dropbox.rest - if not os.path.exists(path): return try: - response = dropbox_client.metadata(dropbox_folder) - except dropbox.rest.ErrorResponse as e: + response = dropbox_client.files_list_folder(dropbox_folder) + except dropbox.exceptions.ApiError as e: # folder not found - if e.status == 404: - response = {"contents": []} + if isinstance(e.error, dropbox.files.ListFolderError): + response = frappe._dict({"entries": []}) else: raise @@ -255,17 +120,112 @@ def upload_from_folder(path, dropbox_folder, dropbox_client, did_not_upload, err found = False filepath = os.path.join(path, filename) - for file_metadata in response["contents"]: - if (os.path.basename(filepath) == os.path.basename(file_metadata["path"]) - and os.stat(encode(filepath)).st_size == int(file_metadata["bytes"])): + for file_metadata in response.entries: + if (os.path.basename(filepath) == file_metadata.name + and os.stat(encode(filepath)).st_size == int(file_metadata.size)): found = True break if not found: try: - dropbox_client = upload_file_to_dropbox(filepath, dropbox_folder, dropbox_client) + upload_file_to_dropbox(filepath, dropbox_folder, dropbox_client) except Exception: did_not_upload.append(filename) error_log.append(frappe.get_traceback()) - return dropbox_client +def upload_file_to_dropbox(filename, folder, dropbox_client): + create_folder_if_not_exists(folder, dropbox_client) + chunk_size = 4 * 1024 * 1024 + file_size = os.path.getsize(filename) + mode = (dropbox.files.WriteMode.overwrite) + + f = open(encode(filename), 'rb') + path = "{0}/{1}".format(folder, os.path.basename(filename)) + + if file_size <= chunk_size: + dropbox_client.files_upload(f.read(), path, mode) + else: + upload_session_start_result = dropbox_client.files_upload_session_start(f.read(chunk_size)) + cursor = dropbox.files.UploadSessionCursor(session_id=upload_session_start_result.session_id, offset=f.tell()) + commit = dropbox.files.CommitInfo(path=path, mode=mode) + + while f.tell() < file_size: + if ((file_size - f.tell()) <= chunk_size): + dropbox_client.files_upload_session_finish(f.read(chunk_size), cursor, commit) + else: + dropbox_client.files_upload_session_append(f.read(chunk_size), cursor.session_id,cursor.offset) + cursor.offset = f.tell() + +def create_folder_if_not_exists(folder, dropbox_client): + try: + dropbox_client.files_get_metadata(folder) + except dropbox.exceptions.ApiError as e: + # folder not found + if isinstance(e.error, dropbox.files.GetMetadataError): + dropbox_client.files_create_folder(folder) + else: + raise + +def get_dropbox_settings(redirect_uri=False): + settings = frappe.get_doc("Dropbox Settings") + app_details = { + "app_key": settings.app_access_key or frappe.conf.dropbox_access_key, + "app_secret": settings.get_password(fieldname="app_secret_key", raise_exception=False) + if settings.app_secret_key else frappe.conf.dropbox_secret_key, + 'access_token': settings.get_password('dropbox_access_token', raise_exception=False) + if settings.dropbox_access_token else '' + } + + if redirect_uri: + app_details.update({ + 'rediret_uri': get_request_site_address(True) \ + + '/api/method/frappe.integrations.doctype.dropbox_settings.dropbox_settings.dropbox_auth_finish' \ + if settings.app_secret_key else frappe.conf.dropbox_rediret_uri, + }) + + if not app_details['app_key'] or not app_details['app_secret']: + raise Exception(_("Please set Dropbox access keys in your site config")) + + return app_details + +@frappe.whitelist() +def get_dropbox_authorize_url(): + app_details = get_dropbox_settings(redirect_uri=True) + dropbox_oauth_flow = dropbox.DropboxOAuth2Flow( + app_details["app_key"], + app_details["app_secret"], + app_details["rediret_uri"], + {}, + "dropbox-auth-csrf-token" + ) + + auth_url = dropbox_oauth_flow.start() + return {"auth_url": auth_url} + +@frappe.whitelist() +def dropbox_auth_finish(): + app_details = get_dropbox_settings(redirect_uri=True) + callback = frappe.form_dict + close = '

' + _('Please close this window') + '

' + + dropbox_oauth_flow = dropbox.DropboxOAuth2Flow( + app_details["app_key"], + app_details["app_secret"], + app_details["rediret_uri"], + {'dropbox-auth-csrf-token': callback.state}, + "dropbox-auth-csrf-token" + ) + + if callback.state or callback.code: + token = dropbox_oauth_flow.finish({'state': callback.state, 'code': callback.code}) + frappe.db.set_value("Dropbox Settings", None, 'dropbox_access_token', token.access_token) + frappe.db.commit() + else: + frappe.respond_as_web_page(_("Dropbox Setup"), + _("Illegal Access Token. Please try again") + close, + indicator_color='red', + http_status_code=frappe.AuthenticationError.http_status_code) + + frappe.respond_as_web_page(_("Dropbox Setup"), + _("Dropbox access is approved!") + close, + indicator_color='green') From 0c6b1c4481fa3114e2f059d56eaffa50c1e25acb Mon Sep 17 00:00:00 2001 From: Saurabh Date: Mon, 19 Jun 2017 21:39:09 +0530 Subject: [PATCH 2/4] [fix] fixes to oauth 2 token generation for frappe cloud users --- .../dropbox_settings/dropbox_settings.js | 13 +++++++- .../dropbox_settings/dropbox_settings.py | 31 +++++++++++++++---- 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.js b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.js index 8b4215baac..272f8060ac 100644 --- a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.js +++ b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.js @@ -8,7 +8,7 @@ frappe.ui.form.on('Dropbox Settings', { }, allow_dropbox_access: function(frm) { - if ((frm.doc.app_access_key && frm.doc.app_secret_key) || frm.doc.dropbox_setup_via_site_config) { + if (frm.doc.app_access_key && frm.doc.app_secret_key) { frappe.call({ method: "frappe.integrations.doctype.dropbox_settings.dropbox_settings.get_dropbox_authorize_url", freeze: true, @@ -19,6 +19,17 @@ frappe.ui.form.on('Dropbox Settings', { } }) } + else if (frm.doc.dropbox_setup_via_site_config) { + frappe.call({ + method: "frappe.integrations.doctype.dropbox_settings.dropbox_settings.get_redirect_url", + freeze: true, + callback: function(r) { + if(!r.exc) { + window.open(r.message.redirect_to); + } + } + }) + } else { frappe.msgprint(__("Please enter values for App Access Key and App Secret Key")) } diff --git a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py index 479b8189e4..acd04a0d63 100644 --- a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py +++ b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py @@ -10,8 +10,9 @@ from frappe.model.document import Document import dropbox from frappe.utils.backups import new_backup from frappe.utils.background_jobs import enqueue +from urlparse import urlparse, parse_qs from frappe.utils import (cint, split_emails, get_request_site_address, cstr, - get_files_path, get_backups_path, encode) + get_files_path, get_backups_path, encode, get_url) ignore_list = [".DS_Store"] @@ -180,7 +181,8 @@ def get_dropbox_settings(redirect_uri=False): app_details.update({ 'rediret_uri': get_request_site_address(True) \ + '/api/method/frappe.integrations.doctype.dropbox_settings.dropbox_settings.dropbox_auth_finish' \ - if settings.app_secret_key else frappe.conf.dropbox_rediret_uri, + if settings.app_secret_key else frappe.conf.dropbox_broker_site\ + + '/api/method/dropbox_erpnext_broker.www.setup_dropbox.generate_dropbox_access_token', }) if not app_details['app_key'] or not app_details['app_secret']: @@ -188,6 +190,12 @@ def get_dropbox_settings(redirect_uri=False): return app_details +@frappe.whitelist() +def get_redirect_url(): + return { + "redirect_to": "{0}/setup_dropbox?site={1}".format(frappe.conf.dropbox_broker_site, get_url()) + } + @frappe.whitelist() def get_dropbox_authorize_url(): app_details = get_dropbox_settings(redirect_uri=True) @@ -200,10 +208,14 @@ def get_dropbox_authorize_url(): ) auth_url = dropbox_oauth_flow.start() - return {"auth_url": auth_url} + + return { + "auth_url": auth_url, + "args": parse_qs(urlparse(auth_url).query) + } @frappe.whitelist() -def dropbox_auth_finish(): +def dropbox_auth_finish(return_access_token=False): app_details = get_dropbox_settings(redirect_uri=True) callback = frappe.form_dict close = '

' + _('Please close this window') + '

' @@ -218,8 +230,10 @@ def dropbox_auth_finish(): if callback.state or callback.code: token = dropbox_oauth_flow.finish({'state': callback.state, 'code': callback.code}) - frappe.db.set_value("Dropbox Settings", None, 'dropbox_access_token', token.access_token) - frappe.db.commit() + if return_access_token and token.access_token: + return token.access_token, callback.state + + set_dropbox_access_token(token.access_token) else: frappe.respond_as_web_page(_("Dropbox Setup"), _("Illegal Access Token. Please try again") + close, @@ -229,3 +243,8 @@ def dropbox_auth_finish(): frappe.respond_as_web_page(_("Dropbox Setup"), _("Dropbox access is approved!") + close, indicator_color='green') + +@frappe.whitelist(allow_guest=True) +def set_dropbox_access_token(access_token): + frappe.db.set_value("Dropbox Settings", None, 'dropbox_access_token', access_token) + frappe.db.commit() From ec16d11ae639c9a9bb2405cf44278bccd3efd5fd Mon Sep 17 00:00:00 2001 From: Saurabh Date: Tue, 20 Jun 2017 15:47:36 +0530 Subject: [PATCH 3/4] generate oauth2 access token from oauth1 access token --- .../dropbox_settings/dropbox_settings.js | 14 ++++------ .../dropbox_settings/dropbox_settings.json | 4 +-- .../dropbox_settings/dropbox_settings.py | 28 +++++++++++++++++-- 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.js b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.js index 272f8060ac..a8af7126b9 100644 --- a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.js +++ b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.js @@ -37,14 +37,12 @@ frappe.ui.form.on('Dropbox Settings', { take_backup: function(frm) { if ((frm.doc.app_access_key && frm.doc.app_secret_key) || frm.doc.dropbox_setup_via_site_config){ - if (frm.doc.dropbox_access_token) { - frm.add_custom_button(__("Take Backup Now"), function(frm){ - frappe.call({ - method: "frappe.integrations.doctype.dropbox_settings.dropbox_settings.take_backup", - freeze: true - }) - }).addClass("btn-primary") - } + frm.add_custom_button(__("Take Backup Now"), function(frm){ + frappe.call({ + method: "frappe.integrations.doctype.dropbox_settings.dropbox_settings.take_backup", + freeze: true + }) + }).addClass("btn-primary") } } }); diff --git a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.json b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.json index 5e0e6dc508..cbe1fe8b1a 100644 --- a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.json +++ b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.json @@ -262,7 +262,7 @@ "columns": 0, "fieldname": "dropbox_access_token", "fieldtype": "Password", - "hidden": 0, + "hidden": 1, "ignore_user_permissions": 0, "ignore_xss_filter": 0, "in_filter": 0, @@ -325,7 +325,7 @@ "issingle": 1, "istable": 0, "max_attachments": 0, - "modified": "2017-06-19 04:02:22.472465", + "modified": "2017-06-20 15:45:33.683827", "modified_by": "Administrator", "module": "Integrations", "name": "Dropbox Settings", diff --git a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py index acd04a0d63..24735a5391 100644 --- a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py +++ b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py @@ -7,10 +7,11 @@ import frappe import os from frappe import _ from frappe.model.document import Document -import dropbox +import dropbox, json from frappe.utils.backups import new_backup from frappe.utils.background_jobs import enqueue from urlparse import urlparse, parse_qs +from frappe.integrations.utils import make_post_request from frappe.utils import (cint, split_emails, get_request_site_address, cstr, get_files_path, get_backups_path, encode, get_url) @@ -80,8 +81,16 @@ def backup_to_dropbox(): # upload database dropbox_settings = get_dropbox_settings() + if not dropbox_settings['access_token']: - return + access_token = generate_oauth2_access_token_from_oauth1_token(dropbox_settings) + + if not access_token.get('oauth2_token'): + return + + dropbox_settings['access_token'] = access_token['oauth2_token'] + set_dropbox_access_token(access_token['oauth2_token']) + dropbox_client = dropbox.Dropbox(dropbox_settings['access_token']) backup = new_backup(ignore_files=True) @@ -174,7 +183,9 @@ def get_dropbox_settings(redirect_uri=False): "app_secret": settings.get_password(fieldname="app_secret_key", raise_exception=False) if settings.app_secret_key else frappe.conf.dropbox_secret_key, 'access_token': settings.get_password('dropbox_access_token', raise_exception=False) - if settings.dropbox_access_token else '' + if settings.dropbox_access_token else '', + 'access_key': settings.get_password('dropbox_access_key', raise_exception=False), + 'access_secret': settings.get_password('dropbox_access_secret', raise_exception=False) } if redirect_uri: @@ -248,3 +259,14 @@ def dropbox_auth_finish(return_access_token=False): def set_dropbox_access_token(access_token): frappe.db.set_value("Dropbox Settings", None, 'dropbox_access_token', access_token) frappe.db.commit() + +def generate_oauth2_access_token_from_oauth1_token(dropbox_settings=None): + url = "https://api.dropboxapi.com/2/auth/token/from_oauth1" + headers = {"Content-Type": "application/json"} + auth = (dropbox_settings["app_key"], dropbox_settings["app_secret"]) + data = { + "oauth1_token": dropbox_settings["access_key"], + "oauth1_token_secret": dropbox_settings["access_secret"] + } + + return make_post_request(url, auth=auth, headers=headers, data=json.dumps(data)) From ee13f1bc936c5236107fc0c6c459bf930aa93466 Mon Sep 17 00:00:00 2001 From: Saurabh Date: Tue, 20 Jun 2017 18:39:15 +0530 Subject: [PATCH 4/4] [fix] bypass setup_dropbox page via rest api --- .../dropbox_settings/dropbox_settings.js | 2 +- .../dropbox_settings/dropbox_settings.py | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.js b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.js index a8af7126b9..2e3c707a5e 100644 --- a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.js +++ b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.js @@ -25,7 +25,7 @@ frappe.ui.form.on('Dropbox Settings', { freeze: true, callback: function(r) { if(!r.exc) { - window.open(r.message.redirect_to); + window.open(r.message.auth_url); } } }) diff --git a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py index 24735a5391..2fb512e8a0 100644 --- a/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py +++ b/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py @@ -203,9 +203,18 @@ def get_dropbox_settings(redirect_uri=False): @frappe.whitelist() def get_redirect_url(): - return { - "redirect_to": "{0}/setup_dropbox?site={1}".format(frappe.conf.dropbox_broker_site, get_url()) - } + url = "{0}/api/method/dropbox_erpnext_broker.www.setup_dropbox.get_authotize_url".format(frappe.conf.dropbox_broker_site) + + try: + response = make_post_request(url, data={"site": get_url()}) + if response.get("message"): + return response["message"] + + except Exception as e: + frappe.log_error() + frappe.throw( + _("Something went wrong while generating dropbox access token. Please check error log for more details.") + ) @frappe.whitelist() def get_dropbox_authorize_url(): @@ -235,7 +244,9 @@ def dropbox_auth_finish(return_access_token=False): app_details["app_key"], app_details["app_secret"], app_details["rediret_uri"], - {'dropbox-auth-csrf-token': callback.state}, + { + 'dropbox-auth-csrf-token': callback.state + }, "dropbox-auth-csrf-token" )