From a23dc0a749e65fa650b362f22affec083c4ee933 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 9 Aug 2019 22:13:39 +0530 Subject: [PATCH 01/58] feat: google drive initial bringup --- frappe/boot.py | 6 +- .../doctype/google_drive/__init__.py | 0 .../doctype/google_drive/google_drive.js | 30 ++++ .../doctype/google_drive/google_drive.json | 94 +++++++++++++ .../doctype/google_drive/google_drive.py | 133 ++++++++++++++++++ .../doctype/google_drive/test_google_drive.py | 10 ++ frappe/public/build.json | 1 + frappe/public/js/frappe/form/toolbar.js | 9 ++ .../js/frappe/views/google_drive_uploader.js | 52 +++++++ 9 files changed, 332 insertions(+), 3 deletions(-) create mode 100644 frappe/integrations/doctype/google_drive/__init__.py create mode 100644 frappe/integrations/doctype/google_drive/google_drive.js create mode 100644 frappe/integrations/doctype/google_drive/google_drive.json create mode 100644 frappe/integrations/doctype/google_drive/google_drive.py create mode 100644 frappe/integrations/doctype/google_drive/test_google_drive.py create mode 100644 frappe/public/js/frappe/views/google_drive_uploader.js diff --git a/frappe/boot.py b/frappe/boot.py index 50888fcdd2..3b7e94dc81 100644 --- a/frappe/boot.py +++ b/frappe/boot.py @@ -76,7 +76,7 @@ def get_bootinfo(): bootinfo.calendars = sorted(frappe.get_hooks("calendars")) bootinfo.treeviews = frappe.get_hooks("treeviews") or [] bootinfo.lang_dict = get_lang_dict() - bootinfo.gsuite_enabled = get_gsuite_status() + bootinfo.google_drive_enabled = get_google_drive_status() bootinfo.success_action = get_success_action() bootinfo.update(get_email_accounts(user=frappe.session.user)) bootinfo.energy_points_enabled = is_energy_point_enabled() @@ -258,8 +258,8 @@ def get_unseen_notes(): (select user from `tabNote Seen By` nsb where nsb.parent=`tabNote`.name)''', (frappe.utils.now(), frappe.session.user), as_dict=True) -def get_gsuite_status(): - return (frappe.get_value('Gsuite Settings', None, 'enable') == '1') + def get_google_drive_status(): + return True if frappe.db.exists("Google Drive", {"enable": 1}) else False def get_success_action(): return frappe.get_all("Success Action", fields=["*"]) diff --git a/frappe/integrations/doctype/google_drive/__init__.py b/frappe/integrations/doctype/google_drive/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/frappe/integrations/doctype/google_drive/google_drive.js b/frappe/integrations/doctype/google_drive/google_drive.js new file mode 100644 index 0000000000..9bdd7ca4c5 --- /dev/null +++ b/frappe/integrations/doctype/google_drive/google_drive.js @@ -0,0 +1,30 @@ +// Copyright (c) 2019, Frappe Technologies and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Google Drive', { + refresh: function(frm) { + if (frm.is_new()) { + frm.dashboard.set_headline(__("To use Google Drive, enable Google Settings.")); + } + }, + authorize_google_drive_access: function(frm) { + let reauthorize = 0; + if(frm.doc.authorization_code) { + reauthorize = 1; + } + + frappe.call({ + method: "frappe.integrations.doctype.google_drive.google_drive.authorize_access", + args: { + "g_drive": frm.doc.name, + "reauthorize": reauthorize + }, + callback: function(r) { + if(!r.exc) { + frm.save(); + window.open(r.message.url); + } + } + }); + } +}); diff --git a/frappe/integrations/doctype/google_drive/google_drive.json b/frappe/integrations/doctype/google_drive/google_drive.json new file mode 100644 index 0000000000..f2eb3a2f38 --- /dev/null +++ b/frappe/integrations/doctype/google_drive/google_drive.json @@ -0,0 +1,94 @@ +{ + "autoname": "format:{folder_name}-{reference_doctype}", + "creation": "2019-08-08 13:16:06.783138", + "doctype": "DocType", + "engine": "InnoDB", + "field_order": [ + "enable", + "sb_00", + "user", + "folder_name", + "authorize_google_drive_access", + "authorization_code", + "refresh_token" + ], + "fields": [ + { + "default": "0", + "fieldname": "enable", + "fieldtype": "Check", + "label": "Enable" + }, + { + "depends_on": "enable", + "fieldname": "sb_00", + "fieldtype": "Section Break", + "label": "Google Drive" + }, + { + "fieldname": "user", + "fieldtype": "Link", + "in_list_view": 1, + "label": "User", + "options": "User", + "reqd": 1 + }, + { + "depends_on": "eval:!doc.__islocal", + "fieldname": "authorize_google_drive_access", + "fieldtype": "Button", + "label": "Authorize Google Drive Access" + }, + { + "fieldname": "folder_name", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Folder Name", + "reqd": 1, + "set_only_once": 1, + "unique": 1 + }, + { + "fieldname": "authorization_code", + "fieldtype": "Password", + "label": "Authorization Code" + }, + { + "fieldname": "refresh_token", + "fieldtype": "Password", + "label": "Refresh Token" + } + ], + "modified": "2019-08-09 18:20:58.169056", + "modified_by": "Administrator", + "module": "Integrations", + "name": "Google Drive", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "print": 1, + "read": 1, + "role": "System Manager", + "share": 1, + "write": 1 + }, + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "All", + "share": 1, + "write": 1 + } + ], + "sort_field": "modified", + "sort_order": "ASC", + "track_changes": 1 +} \ No newline at end of file diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py new file mode 100644 index 0000000000..92e96e8522 --- /dev/null +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -0,0 +1,133 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019, Frappe Technologies and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe +import requests +import googleapiclient.discovery +import google.oauth2.credentials + +from frappe import _ +from frappe.model.document import Document +from frappe.utils import get_request_site_address +from six.moves.urllib.parse import quote +from apiclient.http import MediaFileUpload + +SCOPES = "https://www.googleapis.com/auth/drive" + +class GoogleDrive(Document): + + def get_access_token(self): + google_settings = frappe.get_doc("Google Settings") + + if not google_settings.enable: + frappe.throw(_("Google Integration is disabled.")) + + if not self.refresh_token: + button_label = frappe.bold(_("Allow Google Drive Access")) + raise frappe.ValidationError(_("Click on {0} to generate Refresh Token.").format(button_label)) + + data = { + "client_id": google_settings.client_id, + "client_secret": google_settings.get_password(fieldname="client_secret", raise_exception=False), + "refresh_token": self.get_password(fieldname="refresh_token", raise_exception=False), + "grant_type": "refresh_token", + "scope": SCOPES + } + + try: + r = requests.post("https://www.googleapis.com/oauth2/v4/token", data=data).json() + except requests.exceptions.HTTPError: + button_label = frappe.bold(_("Allow Google Drive Access")) + frappe.throw(_("Something went wrong during the token generation. Click on {0} to generate a new one.").format(button_label)) + + return r.get("access_token") + +@frappe.whitelist() +def authorize_access(g_drive, reauthorize=None): + """ + If no Authorization code get it from Google and then request for Refresh Token. + Google Contact Name is set to flags to set_value after Authorization Code is obtained. + """ + + google_settings = frappe.get_doc("Google Settings") + google_drive = frappe.get_doc("Google Drive", g_drive) + + redirect_uri = get_request_site_address(True) + "?cmd=frappe.integrations.doctype.google_drive.google_drive.google_callback" + + if not google_drive.authorization_code or reauthorize: + frappe.cache().hset("google_drive", "google_drive", google_drive.name) + return get_authentication_url(client_id=google_settings.client_id, redirect_uri=redirect_uri) + else: + try: + data = { + "code": google_drive.authorization_code, + "client_id": google_settings.client_id, + "client_secret": google_settings.get_password(fieldname="client_secret", raise_exception=False), + "redirect_uri": redirect_uri, + "grant_type": "authorization_code" + } + r = requests.post("https://www.googleapis.com/oauth2/v4/token", data=data).json() + + if "refresh_token" in r: + frappe.db.set_value("Google Drive", google_drive.name, "refresh_token", r.get("refresh_token")) + frappe.db.commit() + + frappe.local.response["type"] = "redirect" + frappe.local.response["location"] = "/desk#Form/{0}/{1}".format(quote("Google Drive"), quote(google_drive.name)) + + frappe.msgprint(_("Google Drive has been configured.")) + except Exception as e: + frappe.throw(e) + +def get_authentication_url(client_id, redirect_uri): + return { + "url": "https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&response_type=code&prompt=consent&client_id={}&include_granted_scopes=true&scope={}&redirect_uri={}".format(client_id, SCOPES, redirect_uri) + } + +@frappe.whitelist() +def google_callback(code=None): + """ + Authorization code is sent to callback as per the API configuration + """ + google_drive = frappe.cache().hget("google_drive", "google_drive") + frappe.db.set_value("Google Drive", google_drive, "authorization_code", code) + frappe.db.commit() + + authorize_access(google_drive) + +def get_google_drive_object(g_drive): + """ + Returns an object of Google Drive. + """ + google_settings = frappe.get_doc("Google Settings") + account = frappe.get_doc("Google Drive", g_drive) + + credentials_dict = { + "token": account.get_access_token(), + "refresh_token": account.get_password(fieldname="refresh_token", raise_exception=False), + "token_uri": "https://www.googleapis.com/oauth2/v4/token", + "client_id": google_settings.client_id, + "client_secret": google_settings.get_password(fieldname="client_secret", raise_exception=False), + "scopes": "https://www.googleapis.com/auth/drive/v3" + } + + credentials = google.oauth2.credentials.Credentials(**credentials_dict) + google_drive = googleapiclient.discovery.build("drive", "v3", credentials=credentials) + + return google_calendar + +@frappe.whitelist() +def upload_document(doctype, docname, g_drive): + from frappe.utils.print_format import download_pdf + + google_drive = get_google_drive_object(g_drive) + download_pdf(doctype=doctype, docname=docname, format="pdf") + file_metadata = {"name": frappe.local.response.filename} + media = MediaFileUpload(frappe.local.response.filename, mimetype="application/pdf") + + file = google_drive.files().create(body=file_metadata, media_body=media, fields='id').execute() + + + # frappe.local.response.filecontent diff --git a/frappe/integrations/doctype/google_drive/test_google_drive.py b/frappe/integrations/doctype/google_drive/test_google_drive.py new file mode 100644 index 0000000000..f06e13572c --- /dev/null +++ b/frappe/integrations/doctype/google_drive/test_google_drive.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019, Frappe Technologies and Contributors +# See license.txt +from __future__ import unicode_literals + +# import frappe +import unittest + +class TestGoogleDrive(unittest.TestCase): + pass diff --git a/frappe/public/build.json b/frappe/public/build.json index cb41ae7eef..7bec259933 100755 --- a/frappe/public/build.json +++ b/frappe/public/build.json @@ -205,6 +205,7 @@ "public/js/frappe/ui/toolbar/toolbar.js", "public/js/frappe/ui/toolbar/notifications.js", "public/js/frappe/views/communication.js", + "public/js/frappe/views/google_drive_uploader.js", "public/js/frappe/views/translation_manager.js", "public/js/frappe/ui/sort_selector.html", diff --git a/frappe/public/js/frappe/form/toolbar.js b/frappe/public/js/frappe/form/toolbar.js index 43411bd6de..003f4661e2 100644 --- a/frappe/public/js/frappe/form/toolbar.js +++ b/frappe/public/js/frappe/form/toolbar.js @@ -125,6 +125,15 @@ frappe.ui.form.Toolbar = Class.extend({ } } + //Google Drive + if(frappe.boot.google_drive_enabled){ + this.page.add_menu_item(__("Google Drive Upload"), function() { + new frappe.views.GoogleDriveUploader(me.frm);}, true); + this.print_icon = this.page.add_action_icon("fa fa-google", function() { + new frappe.views.GoogleDriveUploader(me.frm); + }); + } + // email if(frappe.model.can_email(null, me.frm) && me.frm.doc.docstatus < 2) { this.page.add_menu_item(__("Email"), function() { diff --git a/frappe/public/js/frappe/views/google_drive_uploader.js b/frappe/public/js/frappe/views/google_drive_uploader.js new file mode 100644 index 0000000000..7c943216b7 --- /dev/null +++ b/frappe/public/js/frappe/views/google_drive_uploader.js @@ -0,0 +1,52 @@ +frappe.views.GoogleDriveUploader = Class.extend({ + init: function(opts) { + $.extend(this, opts); + this.make(); + }, + make: function() { + let me = this; + let uploader = new frappe.ui.Dialog({ + title: __("Upload File to Google Drive"), + fields: [ + { + fieldtype: "Link", + fieldname: "google_drive", + options: "Google Drive", + label: __("Google Drive"), + reqd: 1, + get_query: function() { + return { + "filters": { + "owner": frappe.session.user, + } + } + } + } + ], + primary_action_label: __("Submit"), + primary_action: (d) => { + frappe.show_alert({ + indicator: "red", + message: __("Uploading to Google Drive.") + }); + uploader.hide(); + frappe.call({ + method: "frappe.integrations.doctype.google_drive.google_drive.upload_document", + args: { + doctype: me.doctype, + docname: me.docname, + g_drive: d.google_drive, + }, + callback: function(r) { + frappe.show_alert({ + indicator: "green", + message: __("Document uploaded to Google Drive.") + }); + uploader.hide(); + } + }) + } + }); + uploader.show(); + } +}) \ No newline at end of file From 4e52c6ffa2df6d0468d863047101fc6058a63fac Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 9 Aug 2019 22:18:00 +0530 Subject: [PATCH 02/58] fix: indentation --- frappe/boot.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/boot.py b/frappe/boot.py index 3b7e94dc81..60c5e17cd4 100644 --- a/frappe/boot.py +++ b/frappe/boot.py @@ -258,8 +258,8 @@ def get_unseen_notes(): (select user from `tabNote Seen By` nsb where nsb.parent=`tabNote`.name)''', (frappe.utils.now(), frappe.session.user), as_dict=True) - def get_google_drive_status(): - return True if frappe.db.exists("Google Drive", {"enable": 1}) else False +def get_google_drive_status(): + return True if frappe.db.exists("Google Drive", {"enable": 1}) else False def get_success_action(): return frappe.get_all("Success Action", fields=["*"]) From aff1180e7277741ade2bd19324ee5a1c73c8a37e Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 9 Aug 2019 22:46:52 +0530 Subject: [PATCH 03/58] fix: passsword to data --- frappe/integrations/doctype/google_drive/google_drive.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.json b/frappe/integrations/doctype/google_drive/google_drive.json index f2eb3a2f38..a16a7b271d 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.json +++ b/frappe/integrations/doctype/google_drive/google_drive.json @@ -50,16 +50,16 @@ }, { "fieldname": "authorization_code", - "fieldtype": "Password", + "fieldtype": "Data", "label": "Authorization Code" }, { "fieldname": "refresh_token", - "fieldtype": "Password", + "fieldtype": "Data", "label": "Refresh Token" } ], - "modified": "2019-08-09 18:20:58.169056", + "modified": "2019-08-09 19:16:28.614921", "modified_by": "Administrator", "module": "Integrations", "name": "Google Drive", From c39b102d796146fd56c3c1baff2183c8c670d5db Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 11 Aug 2019 09:07:20 +0530 Subject: [PATCH 04/58] feat: Google Drive doc pdf uploader --- .../doctype/google_drive/google_drive.json | 16 ++++- .../doctype/google_drive/google_drive.py | 60 +++++++++++++++---- frappe/public/js/frappe/form/print.js | 52 ++++++++++++++++ .../frappe/form/templates/print_layout.html | 42 ++++++------- frappe/public/js/frappe/form/toolbar.js | 9 --- .../js/frappe/views/google_drive_uploader.js | 52 ---------------- 6 files changed, 138 insertions(+), 93 deletions(-) delete mode 100644 frappe/public/js/frappe/views/google_drive_uploader.js diff --git a/frappe/integrations/doctype/google_drive/google_drive.json b/frappe/integrations/doctype/google_drive/google_drive.json index a16a7b271d..1ab858ada3 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.json +++ b/frappe/integrations/doctype/google_drive/google_drive.json @@ -7,8 +7,10 @@ "enable", "sb_00", "user", - "folder_name", "authorize_google_drive_access", + "column_break_5", + "folder_name", + "folder_id", "authorization_code", "refresh_token" ], @@ -57,9 +59,19 @@ "fieldname": "refresh_token", "fieldtype": "Data", "label": "Refresh Token" + }, + { + "fieldname": "column_break_5", + "fieldtype": "Column Break" + }, + { + "fieldname": "folder_id", + "fieldtype": "Data", + "label": "Folder ID", + "read_only": 1 } ], - "modified": "2019-08-09 19:16:28.614921", + "modified": "2019-08-11 05:17:36.862158", "modified_by": "Administrator", "module": "Integrations", "name": "Google Drive", diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index 92e96e8522..f06dc50386 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -9,10 +9,13 @@ import googleapiclient.discovery import google.oauth2.credentials from frappe import _ +from googleapiclient.errors import HttpError from frappe.model.document import Document from frappe.utils import get_request_site_address from six.moves.urllib.parse import quote from apiclient.http import MediaFileUpload +from frappe.utils.file_manager import save_file, get_file_url +from frappe.utils.print_format import download_pdf SCOPES = "https://www.googleapis.com/auth/drive" @@ -114,20 +117,57 @@ def get_google_drive_object(g_drive): } credentials = google.oauth2.credentials.Credentials(**credentials_dict) - google_drive = googleapiclient.discovery.build("drive", "v3", credentials=credentials) + google_drive_object = googleapiclient.discovery.build("drive", "v3", credentials=credentials) - return google_calendar + return google_drive_object, account + +def create_folder_in_google_drive(google_drive_object, account): + """ + Create a folder on Drive, returns the newely created folders ID + """ + file_metadata = { + "name": account.folder_name, + "mimeType": "application/vnd.google-apps.folder" + } + folder = google_drive_object.files().create(body=file_metadata, fields="id").execute() + frappe.db.set_value("Google Drive", account.name, "folder_id", folder.get("id")) @frappe.whitelist() -def upload_document(doctype, docname, g_drive): - from frappe.utils.print_format import download_pdf +def upload_document_to_google_drive(doctype, docname, g_drive, format, letterhead): + """ + Uploads Document to Folder specified in Google Drive Doc. + """ + google_drive_object, account = get_google_drive_object(g_drive) - google_drive = get_google_drive_object(g_drive) - download_pdf(doctype=doctype, docname=docname, format="pdf") - file_metadata = {"name": frappe.local.response.filename} - media = MediaFileUpload(frappe.local.response.filename, mimetype="application/pdf") + if not account.folder_id: + create_folder_in_google_drive(google_drive_object, account) + account.load_from_db() - file = google_drive.files().create(body=file_metadata, media_body=media, fields='id').execute() + download_pdf(doctype=doctype, name=docname, format=format, no_letterhead=letterhead) + filename = frappe.local.response.filename.replace(".pdf", "-{0}.pdf".format(frappe.generate_hash(length=5))) + filecontent = frappe.local.response.filecontent - # frappe.local.response.filecontent + upload_file = save_file(filename, filecontent, doctype, docname) + + if not upload_file: + frappe.throw(_("Could not upload pdf to Google Drive")) + + fileurl = upload_file.file_url or upload_file.file_name + file_metadata = { + "name": filename, + "parents": [account.folder_id] + } + + media = MediaFileUpload(get_absolute_path(fileurl), mimetype="application/pdf") + + try: + file = google_drive_object.files().create(body=file_metadata, media_body=media, fields="id").execute() + except HttpError as e: + frappe.msgprint(_("Google Drive - Could not upload file - Error Code {0}").format(e.resp.status)) + +def get_absolute_path(filename): + filename = filename.replace("/files/", "") + file_path = frappe.utils.get_path("public", "files", filename).replace("./", "") + + return "{0}/sites/{1}".format(frappe.utils.get_bench_path(), file_path) \ No newline at end of file diff --git a/frappe/public/js/frappe/form/print.js b/frappe/public/js/frappe/form/print.js index ec78b30c8a..1c180281a0 100644 --- a/frappe/public/js/frappe/form/print.js +++ b/frappe/public/js/frappe/form/print.js @@ -146,6 +146,8 @@ frappe.ui.form.PrintPreview = Class.extend({ frappe.set_route("print-format-builder"); }, __("New Custom Print Format"), __("Start")); }); + + this.google_drive_upload(); }, setup_keyboard_shortcuts() { this.wrapper.find('.print-toolbar a.btn-default').each((i, el) => { @@ -452,6 +454,56 @@ frappe.ui.form.PrintPreview = Class.extend({ frappe.throw(__("No Printer is Available.")); } }); + }, + google_drive_upload: function() { + var me = this; + this.wrapper.find(".btn-upload-drive").click(function () { + let uploader = new frappe.ui.Dialog({ + title: __("Upload File to Google Drive"), + fields: [ + { + fieldtype: "Link", + fieldname: "google_drive", + options: "Google Drive", + label: __("Google Drive"), + reqd: 1, + get_query: function() { + return { + "filters": { + "owner": frappe.session.user, + } + } + } + } + ], + primary_action_label: __("Submit"), + primary_action: (d) => { + frappe.show_alert({ + indicator: "red", + message: __("Uploading to Google Drive.") + }) + uploader.hide(); + + frappe.call({ + method: "frappe.integrations.doctype.google_drive.google_drive.upload_document_to_google_drive", + args: { + doctype: me.frm.doc.doctype, + docname: me.frm.doc.name, + g_drive: d.google_drive, + format: me.selected_format(), + letterhead: me.with_letterhead() ? "0" : "1" + }, + callback: function(r) { + frappe.show_alert({ + indicator: "green", + message: __("Document uploaded to Google Drive.") + }); + } + }) + } + }); + uploader.show(); + }); } }); diff --git a/frappe/public/js/frappe/form/templates/print_layout.html b/frappe/public/js/frappe/form/templates/print_layout.html index 5446ea6425..59f448f27f 100644 --- a/frappe/public/js/frappe/form/templates/print_layout.html +++ b/frappe/public/js/frappe/form/templates/print_layout.html @@ -7,33 +7,35 @@ placeholder="{{ __("Language") }}">
- -
-
+ + + diff --git a/frappe/public/js/frappe/form/toolbar.js b/frappe/public/js/frappe/form/toolbar.js index 003f4661e2..43411bd6de 100644 --- a/frappe/public/js/frappe/form/toolbar.js +++ b/frappe/public/js/frappe/form/toolbar.js @@ -125,15 +125,6 @@ frappe.ui.form.Toolbar = Class.extend({ } } - //Google Drive - if(frappe.boot.google_drive_enabled){ - this.page.add_menu_item(__("Google Drive Upload"), function() { - new frappe.views.GoogleDriveUploader(me.frm);}, true); - this.print_icon = this.page.add_action_icon("fa fa-google", function() { - new frappe.views.GoogleDriveUploader(me.frm); - }); - } - // email if(frappe.model.can_email(null, me.frm) && me.frm.doc.docstatus < 2) { this.page.add_menu_item(__("Email"), function() { diff --git a/frappe/public/js/frappe/views/google_drive_uploader.js b/frappe/public/js/frappe/views/google_drive_uploader.js deleted file mode 100644 index 7c943216b7..0000000000 --- a/frappe/public/js/frappe/views/google_drive_uploader.js +++ /dev/null @@ -1,52 +0,0 @@ -frappe.views.GoogleDriveUploader = Class.extend({ - init: function(opts) { - $.extend(this, opts); - this.make(); - }, - make: function() { - let me = this; - let uploader = new frappe.ui.Dialog({ - title: __("Upload File to Google Drive"), - fields: [ - { - fieldtype: "Link", - fieldname: "google_drive", - options: "Google Drive", - label: __("Google Drive"), - reqd: 1, - get_query: function() { - return { - "filters": { - "owner": frappe.session.user, - } - } - } - } - ], - primary_action_label: __("Submit"), - primary_action: (d) => { - frappe.show_alert({ - indicator: "red", - message: __("Uploading to Google Drive.") - }); - uploader.hide(); - frappe.call({ - method: "frappe.integrations.doctype.google_drive.google_drive.upload_document", - args: { - doctype: me.doctype, - docname: me.docname, - g_drive: d.google_drive, - }, - callback: function(r) { - frappe.show_alert({ - indicator: "green", - message: __("Document uploaded to Google Drive.") - }); - uploader.hide(); - } - }) - } - }); - uploader.show(); - } -}) \ No newline at end of file From 50f42ffba5241e70986aea779f049a5ec2a0101b Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 11 Aug 2019 16:20:39 +0530 Subject: [PATCH 05/58] feat: system backup to drive --- frappe/hooks.py | 6 +- .../doctype/google_drive/google_drive.json | 46 +- .../doctype/google_drive/google_drive.py | 106 ++++- .../doctype/gsuite_settings/__init__.py | 0 .../gsuite_settings/gsuite_settings.js | 42 -- .../gsuite_settings/gsuite_settings.json | 404 ------------------ .../gsuite_settings/gsuite_settings.py | 87 ---- .../doctype/gsuite_templates/__init__.py | 0 .../gsuite_templates/gsuite_templates.js | 41 -- .../gsuite_templates/gsuite_templates.json | 228 ---------- .../gsuite_templates/gsuite_templates.py | 93 ---- .../gsuite_templates/test_gsuite_templates.py | 10 - frappe/public/js/frappe/form/print.js | 6 +- 13 files changed, 125 insertions(+), 944 deletions(-) delete mode 100644 frappe/integrations/doctype/gsuite_settings/__init__.py delete mode 100644 frappe/integrations/doctype/gsuite_settings/gsuite_settings.js delete mode 100644 frappe/integrations/doctype/gsuite_settings/gsuite_settings.json delete mode 100644 frappe/integrations/doctype/gsuite_settings/gsuite_settings.py delete mode 100644 frappe/integrations/doctype/gsuite_templates/__init__.py delete mode 100644 frappe/integrations/doctype/gsuite_templates/gsuite_templates.js delete mode 100644 frappe/integrations/doctype/gsuite_templates/gsuite_templates.json delete mode 100644 frappe/integrations/doctype/gsuite_templates/gsuite_templates.py delete mode 100644 frappe/integrations/doctype/gsuite_templates/test_gsuite_templates.py diff --git a/frappe/hooks.py b/frappe/hooks.py index 0b0e03ff61..c233651e6d 100644 --- a/frappe/hooks.py +++ b/frappe/hooks.py @@ -192,7 +192,8 @@ scheduler_events = { ], "daily_long": [ "frappe.integrations.doctype.dropbox_settings.dropbox_settings.take_backups_daily", - "frappe.integrations.doctype.s3_backup_settings.s3_backup_settings.take_backups_daily" + "frappe.integrations.doctype.s3_backup_settings.s3_backup_settings.take_backups_daily", + "frappe.integrations.doctype.google_drive.google_drive.daily_backup" ], "weekly_long": [ "frappe.integrations.doctype.dropbox_settings.dropbox_settings.take_backups_weekly", @@ -200,7 +201,8 @@ scheduler_events = { "frappe.utils.change_log.check_for_update", "frappe.desk.doctype.route_history.route_history.flush_old_route_records", "frappe.desk.form.document_follow.send_weekly_updates", - "frappe.social.doctype.energy_point_log.energy_point_log.send_weekly_summary" + "frappe.social.doctype.energy_point_log.energy_point_log.send_weekly_summary", + "frappe.integrations.doctype.google_drive.google_drive.weekly_backup" ], "monthly": [ "frappe.email.doctype.auto_email_report.auto_email_report.send_monthly", diff --git a/frappe/integrations/doctype/google_drive/google_drive.json b/frappe/integrations/doctype/google_drive/google_drive.json index 1ab858ada3..5233fdc9ab 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.json +++ b/frappe/integrations/doctype/google_drive/google_drive.json @@ -7,12 +7,14 @@ "enable", "sb_00", "user", + "backup_folder_name", "authorize_google_drive_access", "column_break_5", - "folder_name", - "folder_id", - "authorization_code", - "refresh_token" + "backup_folder_id", + "enable_system_backup", + "frequency", + "refresh_token", + "authorization_code" ], "fields": [ { @@ -41,15 +43,6 @@ "fieldtype": "Button", "label": "Authorize Google Drive Access" }, - { - "fieldname": "folder_name", - "fieldtype": "Data", - "in_list_view": 1, - "label": "Folder Name", - "reqd": 1, - "set_only_once": 1, - "unique": 1 - }, { "fieldname": "authorization_code", "fieldtype": "Data", @@ -65,13 +58,34 @@ "fieldtype": "Column Break" }, { - "fieldname": "folder_id", + "depends_on": "enable_system_backup", + "fieldname": "frequency", + "fieldtype": "Select", + "label": "Frequency", + "options": "Daily\nWeekly" + }, + { + "default": "0", + "fieldname": "enable_system_backup", + "fieldtype": "Check", + "label": "Enable System Backup" + }, + { + "fieldname": "backup_folder_name", "fieldtype": "Data", - "label": "Folder ID", + "in_list_view": 1, + "label": "Backup Folder Name", + "set_only_once": 1, + "unique": 1 + }, + { + "fieldname": "backup_folder_id", + "fieldtype": "Data", + "label": "Backup Folder ID", "read_only": 1 } ], - "modified": "2019-08-11 05:17:36.862158", + "modified": "2019-08-11 12:42:41.738678", "modified_by": "Administrator", "module": "Integrations", "name": "Google Drive", diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index f06dc50386..0c7c5be70b 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -7,6 +7,7 @@ import frappe import requests import googleapiclient.discovery import google.oauth2.credentials +import os from frappe import _ from googleapiclient.errors import HttpError @@ -16,11 +17,20 @@ from six.moves.urllib.parse import quote from apiclient.http import MediaFileUpload from frappe.utils.file_manager import save_file, get_file_url from frappe.utils.print_format import download_pdf +from frappe.utils import get_backups_path, get_files_path +from frappe.utils.backups import new_backup +from frappe.utils import now SCOPES = "https://www.googleapis.com/auth/drive" class GoogleDrive(Document): + def validate(self): + if self.enable_system_backup: + system_backup = frappe.db.exists("Google Drive", {"enable_system_backup": 1}) + if system_backup and not system_backup == self.name: + frappe.throw(_("Google Drive System Backup can be enabled only for one account.")) + def get_access_token(self): google_settings = frappe.get_doc("Google Settings") @@ -122,52 +132,108 @@ def get_google_drive_object(g_drive): return google_drive_object, account def create_folder_in_google_drive(google_drive_object, account): - """ - Create a folder on Drive, returns the newely created folders ID - """ file_metadata = { - "name": account.folder_name, + "name": account.backup_folder_name, "mimeType": "application/vnd.google-apps.folder" } folder = google_drive_object.files().create(body=file_metadata, fields="id").execute() - frappe.db.set_value("Google Drive", account.name, "folder_id", folder.get("id")) + frappe.db.set_value("Google Drive", account.name, "backup_folder_id", folder.get("id")) + +def check_for_folder_in_google_drive(google_drive_object, account): + """ + Create a folder on Drive, returns the newely created folders ID + """ + if not account.backup_folder_id: + create_folder_in_google_drive(google_drive_object, account) + return + + try: + folder = google_drive_object.files().get(fileId=account.backup_folder_id, fields="id").execute() + except HttpError as e: + if e.resp.status == 404: + create_folder_in_google_drive(google_drive_object, account) + else: + frappe.msgprint(_("Google Drive - Could not create folder - Error Code {0}.").format(e)) @frappe.whitelist() def upload_document_to_google_drive(doctype, docname, g_drive, format, letterhead): """ Uploads Document to Folder specified in Google Drive Doc. """ + # Get Google Drive Object google_drive_object, account = get_google_drive_object(g_drive) - if not account.folder_id: - create_folder_in_google_drive(google_drive_object, account) - account.load_from_db() + # Check if folder exists in Google Drive + check_for_folder_in_google_drive(google_drive_object, account) + account.load_from_db() + # Create PDF for doc and append datestring to name download_pdf(doctype=doctype, name=docname, format=format, no_letterhead=letterhead) - - filename = frappe.local.response.filename.replace(".pdf", "-{0}.pdf".format(frappe.generate_hash(length=5))) + filename = frappe.local.response.filename.replace(".pdf", "-{0}.pdf".format(now())) filecontent = frappe.local.response.filecontent - upload_file = save_file(filename, filecontent, doctype, docname) + file_to_upload = save_file(filename, filecontent, doctype, docname) - if not upload_file: + if not file_to_upload: frappe.throw(_("Could not upload pdf to Google Drive")) - fileurl = upload_file.file_url or upload_file.file_name + fileurl = os.path.basename(file_to_upload.file_name or file_to_upload.file_url) + + # parents: Folder id under which the file is to be uploaded file_metadata = { "name": filename, - "parents": [account.folder_id] + "parents": [account.backup_folder_id] } - media = MediaFileUpload(get_absolute_path(fileurl), mimetype="application/pdf") + media = MediaFileUpload(get_absolute_path(fileurl), mimetype="application/pdf", resumable=True) try: - file = google_drive_object.files().create(body=file_metadata, media_body=media, fields="id").execute() + google_drive_object.files().create(body=file_metadata, media_body=media, fields="id").execute() except HttpError as e: - frappe.msgprint(_("Google Drive - Could not upload file - Error Code {0}").format(e.resp.status)) + frappe.msgprint(_("Google Drive - Could not upload file - Error Code {0}").format(e)) -def get_absolute_path(filename): - filename = filename.replace("/files/", "") - file_path = frappe.utils.get_path("public", "files", filename).replace("./", "") +@frappe.whitelist() +def upload_system_backup_to_google_drive(g_drive): + """ + Upload system backup to Google Drive + """ + # Get Google Drive Object + google_drive_object, account = get_google_drive_object(g_drive) + + # Check if folder exists in Google Drive + check_for_folder_in_google_drive(google_drive_object, account) + account.load_from_db() + + backup = new_backup(ignore_files=True) + + fileurl = os.path.basename(backup.backup_path_db) + + file_metadata = { + "name": "Instance Backup-{0}".format(frappe.utils.now()), + "parents": [account.backup_folder_id] + } + + media = MediaFileUpload(get_absolute_path(fileurl, True), mimetype="application/gzip", resumable=True) + + try: + google_drive_object.files().create(body=file_metadata, media_body=media, fields="id").execute() + except HttpError as e: + frappe.msgprint(_("Google Drive - Could not upload backup - Error {0}").format(e)) + +def daily_backup(): + g_drive = frappe.db.exists("Google Drive", {"enable": 1, "enable_system_backup": 1, "frequency": "Daily"}) + if g_drive: + upload_system_backup_to_google_drive(g_drive) + +def weekly_backup(): + g_drive = frappe.db.exists("Google Drive", {"enable": 1, "enable_system_backup": 1, "frequency": "Weekly"}) + if g_drive: + upload_system_backup_to_google_drive(g_drive) + +def get_absolute_path(filename, backup=False): + file_path = os.path.join(frappe.utils.get_files_path()[2:], filename) + + if backup: + file_path = os.path.join(frappe.utils.get_backups_path()[2:], filename) return "{0}/sites/{1}".format(frappe.utils.get_bench_path(), file_path) \ No newline at end of file diff --git a/frappe/integrations/doctype/gsuite_settings/__init__.py b/frappe/integrations/doctype/gsuite_settings/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/integrations/doctype/gsuite_settings/gsuite_settings.js b/frappe/integrations/doctype/gsuite_settings/gsuite_settings.js deleted file mode 100644 index 71db53c5cc..0000000000 --- a/frappe/integrations/doctype/gsuite_settings/gsuite_settings.js +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2017, Frappe Technologies and contributors -// For license information, please see license.txt - -frappe.ui.form.on('GSuite Settings', { - refresh: function(frm) { - frm.clear_custom_buttons(); - }, - - allow_gsuite_access: function(frm) { - if (frm.doc.client_id && frm.doc.client_secret) { - frappe.call({ - method: "frappe.integrations.doctype.gsuite_settings.gsuite_settings.gsuite_callback", - callback: function(r) { - if(!r.exc) { - frm.save(); - window.open(r.message.url); - } - } - }); - } - else { - frappe.msgprint(__("Please enter values for GSuite Access Key and GSuite Access Secret")) - } - }, - run_script_test: function(frm) { - if (frm.doc.client_id && frm.doc.client_secret) { - frappe.call({ - method: "frappe.integrations.doctype.gsuite_settings.gsuite_settings.run_script_test", - callback: function(r) { - if(!r.exc) { - if (r.message == 'ping') { - frappe.msgprint(__('GSuite test executed with success. GSuite integration is correctly configured'),__('GSuite script test')); - } - } - } - }); - } - else { - frappe.msgprint(__("Please enter values for GSuite Access Key and GSuite Access Secret")); - } - } -}); diff --git a/frappe/integrations/doctype/gsuite_settings/gsuite_settings.json b/frappe/integrations/doctype/gsuite_settings/gsuite_settings.json deleted file mode 100644 index 65ed904c74..0000000000 --- a/frappe/integrations/doctype/gsuite_settings/gsuite_settings.json +++ /dev/null @@ -1,404 +0,0 @@ -{ - "allow_copy": 1, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "beta": 0, - "creation": "2017-04-21 16:57:30.264478", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "System", - "editable_grid": 1, - "engine": "InnoDB", - "fields": [ - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "enable", - "fieldtype": "Check", - "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": "Enable", - "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, - "columns": 0, - "depends_on": "eval:doc.enable", - "fieldname": "google_credentials", - "fieldtype": "Section Break", - "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": "Google Credentials", - "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, - "columns": 0, - "depends_on": "", - "fieldname": "client_id", - "fieldtype": "Data", - "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": "Client ID", - "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, - "columns": 0, - "depends_on": "", - "fieldname": "client_secret", - "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": "Client Secret", - "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, - "columns": 0, - "depends_on": "eval:(doc.client_secret && doc.client_id)", - "fieldname": "allow_gsuite_access", - "fieldtype": "Button", - "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": "Allow GSuite access", - "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": 1, - "columns": 0, - "depends_on": "eval:doc.enable", - "fieldname": "google_apps_script", - "fieldtype": "Section Break", - "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": "Google Apps Script", - "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, - "columns": 0, - "default": "https://script.google.com/macros/s/AKfycbxIFOx3301xwtF2IFPJ4pUQGqkNF3hBiBebppWkeKn6fKZRQvk/exec", - "depends_on": "", - "description": "If you aren't using own publish Google Apps Script webapp you can use the default https://script.google.com/macros/s/AKfycbxIFOx3301xwtF2IFPJ4pUQGqkNF3hBiBebppWkeKn6fKZRQvk/exec ", - "fieldname": "script_url", - "fieldtype": "Data", - "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": "Script URL", - "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, - "columns": 0, - "default": "", - "description": "Copy and paste this code into and empty Code.gs in your project at script.google.com", - "fieldname": "script_code", - "fieldtype": "HTML", - "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": "Script Code", - "length": 0, - "no_copy": 0, - "options": "
// ERPNEXT GSuite integration\n//\n\nfunction doGet(e){\n  return ContentService.createTextOutput('ok');\n}\n\nfunction doPost(e) {\n  var p = JSON.parse(e.postData.contents);\n\n  switch(p.exec){\n    case 'new':\n      var url = createDoc(p);\n      result = { 'url': url };\n      break;\n    case 'test':\n      result = { 'test':'ping' , 'version':'1.0'}\n  }\n  return ContentService.createTextOutput(JSON.stringify(result)).setMimeType(ContentService.MimeType.JSON);\n}\n\nfunction replaceVars(body,p){\n  for (key in p) {\n    if (p.hasOwnProperty(key)) {\n      if (p[key] != null) {\n        body.replaceText('{{'+key+'}}', p[key]);\n      }\n    }\n  }    \n}\n\nfunction createDoc(p) {\n  if(p.destination){\n    var folder = DriveApp.getFolderById(p.destination);\n  } else {\n    var folder = DriveApp.getRootFolder();\n  }\n  var template = DriveApp.getFileById( p.template )\n  var newfile = template.makeCopy( p.filename , folder );\n\n  switch(newfile.getMimeType()){\n    case MimeType.GOOGLE_DOCS:\n      var body = DocumentApp.openById(newfile.getId()).getBody();\n      replaceVars(body,p.vars);\n      break;\n    case MimeType.GOOGLE_SHEETS:\n      //TBD\n    case MimeType.GOOGLE_SLIDES:\n      //TBD\n  }\n  return newfile.getUrl()\n}\n\n
", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "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, - "columns": 0, - "depends_on": "eval:(doc.client_id && doc.client_secret && doc.authorization_code && doc.refresh_token && doc.script_url)", - "fieldname": "run_script_test", - "fieldtype": "Button", - "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": "Run Script Test", - "length": 0, - "no_copy": 1, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 1, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "refresh_token", - "fieldtype": "Password", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "refresh_token", - "length": 0, - "no_copy": 1, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 1, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "authorization_code", - "fieldtype": "Password", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Authorization Code", - "length": 0, - "no_copy": 1, - "permlevel": 0, - "precision": "", - "print_hide": 1, - "print_hide_if_no_value": 0, - "read_only": 0, - "remember_last_selected_value": 0, - "report_hide": 1, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "unique": 0 - } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "idx": 0, - "image_view": 0, - "in_create": 1, - "is_submittable": 0, - "issingle": 1, - "istable": 0, - "max_attachments": 0, - "modified": "2017-10-20 16:11:47.757030", - "modified_by": "Administrator", - "module": "Integrations", - "name": "GSuite Settings", - "name_case": "", - "owner": "Administrator", - "permissions": [ - { - "amend": 0, - "apply_user_permissions": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 0, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 0, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, - "write": 1 - } - ], - "quick_entry": 1, - "read_only": 1, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0 -} \ No newline at end of file diff --git a/frappe/integrations/doctype/gsuite_settings/gsuite_settings.py b/frappe/integrations/doctype/gsuite_settings/gsuite_settings.py deleted file mode 100644 index 4e88ad736c..0000000000 --- a/frappe/integrations/doctype/gsuite_settings/gsuite_settings.py +++ /dev/null @@ -1,87 +0,0 @@ - # Copyright (c) 2017, Frappe Technologies and contributors -# -*- coding: utf-8 -*- -# For license information, please see license.txt - -from __future__ import unicode_literals -import frappe -from frappe import _ -from frappe.model.document import Document -from frappe.utils import get_request_site_address -import requests -from json import dumps -from frappe.utils.response import json_handler - -SCOPES = 'https://www.googleapis.com/auth/drive' - -class GSuiteSettings(Document): - - def get_access_token(self): - if not self.refresh_token: - raise frappe.ValidationError(_("Google GSuite is not configured.")) - data = { - 'client_id': self.client_id, - 'client_secret': self.get_password(fieldname='client_secret',raise_exception=False), - 'refresh_token': self.get_password(fieldname='refresh_token',raise_exception=False), - 'grant_type': "refresh_token", - 'scope': SCOPES - } - try: - r = requests.post('https://www.googleapis.com/oauth2/v4/token', data=data).json() - except requests.exceptions.HTTPError: - frappe.throw(_("Something went wrong during the token generation. Please request again an authorization code.")) - return r.get('access_token') - -@frappe.whitelist() -def gsuite_callback(code=None): - doc = frappe.get_doc("GSuite Settings") - if code is None: - return { - 'url': 'https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&response_type=code&client_id={}&scope={}&redirect_uri={}?cmd=frappe.integrations.doctype.gsuite_settings.gsuite_settings.gsuite_callback'.format(doc.client_id, SCOPES, get_request_site_address(True)) - } - else: - try: - data = {'code': code, - 'client_id': doc.client_id, - 'client_secret': doc.get_password(fieldname='client_secret',raise_exception=False), - 'redirect_uri': get_request_site_address(True) + '?cmd=frappe.integrations.doctype.gsuite_settings.gsuite_settings.gsuite_callback', - 'grant_type': 'authorization_code'} - r = requests.post('https://www.googleapis.com/oauth2/v4/token', data=data).json() - frappe.db.set_value("Gsuite Settings", None, "authorization_code", code) - if 'refresh_token' in r: - frappe.db.set_value("Gsuite Settings", None, "refresh_token", r['refresh_token']) - frappe.db.commit() - return - except Exception as e: - frappe.throw(e.message) - -def run_gsuite_script(option, filename = None, template_id = None, destination_id = None, json_data = None): - gdoc = frappe.get_doc('GSuite Settings') - if gdoc.script_url: - data = { - 'exec': option, - 'filename': filename, - 'template': template_id, - 'destination': destination_id, - 'vars' : json_data - } - headers = {'Authorization': 'Bearer {}'.format( gdoc.get_access_token() )} - - try: - r = requests.post(gdoc.script_url, headers=headers, data=dumps(data, default=json_handler, separators=(',',':'))) - except Exception as e: - frappe.throw(e.message) - - try: - r = r.json() - except: - # if request doesn't return json show HTML ask permissions or to identify the error on google side - frappe.throw(r.text) - - return r - else: - frappe.throw(_('Please set script URL on Gsuite Settings')) - -@frappe.whitelist() -def run_script_test(): - r = run_gsuite_script('test') - return r['test'] diff --git a/frappe/integrations/doctype/gsuite_templates/__init__.py b/frappe/integrations/doctype/gsuite_templates/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/frappe/integrations/doctype/gsuite_templates/gsuite_templates.js b/frappe/integrations/doctype/gsuite_templates/gsuite_templates.js deleted file mode 100644 index ddaa740afd..0000000000 --- a/frappe/integrations/doctype/gsuite_templates/gsuite_templates.js +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2017, Frappe Technologies and contributors -// For license information, please see license.txt - -frappe.ui.form.on('GSuite Templates', { - refresh: function(frm) { - if (frm.is_new()) { - // if doc is new, get all options immediately - frm.trigger('set_available_docs'); - frm.trigger('set_available_folders'); - } - }, - set_available_docs: function(frm) { - frappe.call({ - // get documents from Google Drive - method: 'frappe.integrations.doctype.gsuite_templates.gsuite_templates.get_gdrive_docs', - callback: function(res) { - // set available documents as options - set_gsuite_template_options(frm, 'template_id', res); - } - }); - }, - set_available_folders: function(frm) { - frappe.call({ - // get folders from Google Drive - method: 'frappe.integrations.doctype.gsuite_templates.gsuite_templates.get_gdrive_folders', - callback: function(res) { - // set available folders as options - set_gsuite_template_options(frm, 'destination_id', res); - } - }); - }, -}); - -const set_gsuite_template_options = function(frm, field, data) { - var options = []; - (data.message || []).forEach(function(row){ - options.push({'value': row.id, 'label': row.name}); - }); - frm.set_df_property(field, 'options', options); -}; - diff --git a/frappe/integrations/doctype/gsuite_templates/gsuite_templates.json b/frappe/integrations/doctype/gsuite_templates/gsuite_templates.json deleted file mode 100644 index e0e047a671..0000000000 --- a/frappe/integrations/doctype/gsuite_templates/gsuite_templates.json +++ /dev/null @@ -1,228 +0,0 @@ -{ - "allow_copy": 0, - "allow_events_in_timeline": 0, - "allow_guest_to_view": 0, - "allow_import": 0, - "allow_rename": 0, - "autoname": "field:template_name", - "beta": 0, - "creation": "2017-04-24 09:53:41.813982", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "document_type": "Setup", - "editable_grid": 1, - "engine": "InnoDB", - "fields": [ - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "template_name", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Template Name", - "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": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 1 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "related_doctype", - "fieldtype": "Link", - "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": "Related DocType", - "length": 0, - "no_copy": 0, - "options": "DocType", - "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, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "template_id", - "fieldtype": "Select", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Template ID", - "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": 1, - "search_index": 0, - "set_only_once": 1, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "default": "New Document for {name} ", - "fetch_if_empty": 0, - "fieldname": "document_name", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "Document Name", - "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": 1, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, - { - "allow_bulk_edit": 0, - "allow_in_quick_entry": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fetch_if_empty": 0, - "fieldname": "destination_id", - "fieldtype": "Select", - "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": "Destination ID", - "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": 1, - "translatable": 0, - "unique": 0 - } - ], - "has_web_view": 0, - "hide_toolbar": 0, - "idx": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "modified": "2019-04-14 00:13:49.999149", - "modified_by": "Administrator", - "module": "Integrations", - "name": "GSuite Templates", - "name_case": "", - "owner": "Administrator", - "permissions": [ - { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, - "write": 1 - } - ], - "quick_entry": 0, - "read_only": 0, - "show_name_in_global_search": 0, - "sort_field": "modified", - "sort_order": "DESC", - "track_changes": 1, - "track_seen": 0, - "track_views": 0 -} \ No newline at end of file diff --git a/frappe/integrations/doctype/gsuite_templates/gsuite_templates.py b/frappe/integrations/doctype/gsuite_templates/gsuite_templates.py deleted file mode 100644 index 66028a13d4..0000000000 --- a/frappe/integrations/doctype/gsuite_templates/gsuite_templates.py +++ /dev/null @@ -1,93 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2017, Frappe Technologies and contributors -# For license information, please see license.txt - -from __future__ import unicode_literals -import requests -import frappe -from frappe import _ -from frappe.model.document import Document -from frappe.integrations.doctype.gsuite_settings.gsuite_settings import run_gsuite_script - -class GSuiteTemplates(Document): - pass - -@frappe.whitelist() -def create_gsuite_doc(doctype, docname, gs_template=None): - templ = frappe.get_doc('GSuite Templates', gs_template) - doc = frappe.get_doc(doctype, docname) - - if not doc.has_permission("read"): - raise frappe.PermissionError - - json_data = doc.as_dict() - filename = templ.document_name.format(**json_data) - - response = run_gsuite_script('new', filename, templ.template_id, templ.destination_id, json_data) - - _file = frappe.get_doc({ - "doctype": "File", - "file_url": response['url'], - "file_name": filename, - "attached_to_doctype": doctype, - "attached_to_name": docname, - "attached_to_field": True, - "folder": "Home/Attachments"}) - _file.save() - - comment = frappe.get_doc(doctype, docname).add_comment("Attachment", - _("added {0}").format("{file_name}{icon}".format(**{ - "icon": ' ' if _file.is_private else "", - "file_url": _file.file_url.replace("#", "%23") if _file.file_name else _file.file_url, - "file_name": _file.file_name or _file.file_url - }))) - - return { - "name": _file.name, - "file_name": _file.file_name, - "file_url": _file.file_url, - "is_private": _file.is_private, - "comment": comment.as_dict() if comment else {} - } - -@frappe.whitelist() -def get_gdrive_docs(): - """ Return a list of Google Docs files in Google Drive """ - return get_gdrive_files('application/vnd.google-apps.document') - -@frappe.whitelist() -def get_gdrive_folders(): - """ Return a list of folders in Google Drive """ - return get_gdrive_files('application/vnd.google-apps.folder') - -def get_gdrive_files(mime_type): - """ Get a list of files of the specified mime_type from Google Drive - - returns [ - { - "kind": "drive#file", - "id": "sf_lk-U6lYhVvdgsdf98cvkbj87rl6piFtnLEN9oNsrg", - "name": "My File Name", - "mimeType": mime_type - } - ] - """ - settings = frappe.get_single("GSuite Settings") - token = settings.get_access_token() - url = 'https://www.googleapis.com/drive/v3/files' - - params = { - "q": "mimeType='{}'".format(mime_type) - } - - headers = { - 'Authorization': 'Bearer {}'.format(token), - 'Accept': 'application/json' - } - - try: - response = requests.get(url, params=params, headers=headers) - except requests.exceptions.RequestException as err: - frappe.throw(err) - - return response.json().get('files') diff --git a/frappe/integrations/doctype/gsuite_templates/test_gsuite_templates.py b/frappe/integrations/doctype/gsuite_templates/test_gsuite_templates.py deleted file mode 100644 index aad8e9fae6..0000000000 --- a/frappe/integrations/doctype/gsuite_templates/test_gsuite_templates.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2017, Frappe Technologies and Contributors -# See license.txt -from __future__ import unicode_literals - -import frappe -import unittest - -class TestGSuiteTemplates(unittest.TestCase): - pass diff --git a/frappe/public/js/frappe/form/print.js b/frappe/public/js/frappe/form/print.js index 1c180281a0..855e851b0f 100644 --- a/frappe/public/js/frappe/form/print.js +++ b/frappe/public/js/frappe/form/print.js @@ -470,6 +470,7 @@ frappe.ui.form.PrintPreview = Class.extend({ get_query: function() { return { "filters": { + "enable": 1, "owner": frappe.session.user, } } @@ -482,7 +483,10 @@ frappe.ui.form.PrintPreview = Class.extend({ indicator: "red", message: __("Uploading to Google Drive.") }) + uploader.hide(); + uploader.disable_primary_action(); + uploader.clear(); frappe.call({ method: "frappe.integrations.doctype.google_drive.google_drive.upload_document_to_google_drive", @@ -493,7 +497,7 @@ frappe.ui.form.PrintPreview = Class.extend({ format: me.selected_format(), letterhead: me.with_letterhead() ? "0" : "1" }, - callback: function(r) { + callback: function() { frappe.show_alert({ indicator: "green", message: __("Document uploaded to Google Drive.") From 47450d5a43329ad7201b6924eb1d9d26b64d4dce Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 11 Aug 2019 19:04:14 +0530 Subject: [PATCH 06/58] fix: add take backup button --- .../doctype/google_drive/google_drive.js | 18 ++++++++++++++++++ .../doctype/google_drive/google_drive.py | 2 ++ 2 files changed, 20 insertions(+) diff --git a/frappe/integrations/doctype/google_drive/google_drive.js b/frappe/integrations/doctype/google_drive/google_drive.js index 9bdd7ca4c5..248a616394 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.js +++ b/frappe/integrations/doctype/google_drive/google_drive.js @@ -6,6 +6,24 @@ frappe.ui.form.on('Google Drive', { if (frm.is_new()) { frm.dashboard.set_headline(__("To use Google Drive, enable Google Settings.")); } + + if (frm.doc.enable_system_backup) { + let sync_button = frm.add_custom_button(__("Take Backup"), function () { + frappe.show_alert({ + indicator: "green", + message: __("Backing up to Google Drive.") + }); + frappe.call({ + method: "frappe.integrations.doctype.google_drive.google_drive.upload_system_backup_to_google_drive", + args: { + "g_drive": frm.doc.name + }, + btn: sync_button + }).then((r) => { + frappe.msgprint(r.message); + }); + }); + } }, authorize_google_drive_access: function(frm) { let reauthorize = 0; diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index 0c7c5be70b..d2f78ddb04 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -220,6 +220,8 @@ def upload_system_backup_to_google_drive(g_drive): except HttpError as e: frappe.msgprint(_("Google Drive - Could not upload backup - Error {0}").format(e)) + return "Google Drive Backup Successful." + def daily_backup(): g_drive = frappe.db.exists("Google Drive", {"enable": 1, "enable_system_backup": 1, "frequency": "Daily"}) if g_drive: From 1791cbf0cc95b6019cb1662dd12ce8729a348f5f Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 11 Aug 2019 19:08:37 +0530 Subject: [PATCH 07/58] fix: hide password fields --- frappe/config/integrations.py | 15 +++++---------- .../doctype/google_drive/google_drive.json | 8 +++++--- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/frappe/config/integrations.py b/frappe/config/integrations.py index bbe3966b29..bfed056546 100644 --- a/frappe/config/integrations.py +++ b/frappe/config/integrations.py @@ -92,16 +92,6 @@ def get_data(): "name": "Google Settings", "description": _("Google API Settings."), }, - { - "type": "doctype", - "name": "GSuite Settings", - "description": _("Enter keys to enable integration with Google GSuite"), - }, - { - "type": "doctype", - "name": "GSuite Templates", - "description": _("Google GSuite Templates to integration with DocTypes"), - }, { "type": "doctype", "name": "Google Contacts", @@ -111,6 +101,11 @@ def get_data(): "type": "doctype", "name": "Google Calendar", "description": _("Google Calendar Integration."), + }, + { + "type": "doctype", + "name": "Google Drive", + "description": _("Google Drive Integration."), } ] } diff --git a/frappe/integrations/doctype/google_drive/google_drive.json b/frappe/integrations/doctype/google_drive/google_drive.json index 5233fdc9ab..612ded6fab 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.json +++ b/frappe/integrations/doctype/google_drive/google_drive.json @@ -45,12 +45,14 @@ }, { "fieldname": "authorization_code", - "fieldtype": "Data", + "fieldtype": "Password", + "hidden": 1, "label": "Authorization Code" }, { "fieldname": "refresh_token", - "fieldtype": "Data", + "fieldtype": "Password", + "hidden": 1, "label": "Refresh Token" }, { @@ -85,7 +87,7 @@ "read_only": 1 } ], - "modified": "2019-08-11 12:42:41.738678", + "modified": "2019-08-11 15:37:45.346890", "modified_by": "Administrator", "module": "Integrations", "name": "Google Drive", From ae1f362d34a1d0d375dd769569f27fb001d3c00e Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 11 Aug 2019 19:30:48 +0530 Subject: [PATCH 08/58] fix: naming --- frappe/integrations/doctype/google_drive/google_drive.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.json b/frappe/integrations/doctype/google_drive/google_drive.json index 612ded6fab..2f25381173 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.json +++ b/frappe/integrations/doctype/google_drive/google_drive.json @@ -1,5 +1,5 @@ { - "autoname": "format:{folder_name}-{reference_doctype}", + "autoname": "field:backup_folder_name", "creation": "2019-08-08 13:16:06.783138", "doctype": "DocType", "engine": "InnoDB", @@ -87,7 +87,7 @@ "read_only": 1 } ], - "modified": "2019-08-11 15:37:45.346890", + "modified": "2019-08-11 16:00:39.521237", "modified_by": "Administrator", "module": "Integrations", "name": "Google Drive", From 4ae9624787282c9bba22827ba654472ced0ef142 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 11 Aug 2019 19:43:22 +0530 Subject: [PATCH 09/58] fix: sync folder name --- .../doctype/google_drive/google_drive.js | 17 +++++++++++++++++ .../doctype/google_drive/google_drive.py | 8 +++++++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.js b/frappe/integrations/doctype/google_drive/google_drive.js index 248a616394..d37ac23a48 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.js +++ b/frappe/integrations/doctype/google_drive/google_drive.js @@ -24,6 +24,23 @@ frappe.ui.form.on('Google Drive', { }); }); } + if (!frm.doc.backup_folder_id) { + let sync_button = frm.add_custom_button(__("Create Folder in Google Drive"), function () { + frappe.show_alert({ + indicator: "green", + message: __("Creating folder in Google Drive.") + }); + frappe.call({ + method: "frappe.integrations.doctype.google_drive.google_drive.create_folder_in_google_drive", + args: { + "g_drive": frm.doc.name + }, + btn: sync_button + }).then((r) => { + frappe.msgprint(r.message); + }); + }); + } }, authorize_google_drive_access: function(frm) { let reauthorize = 0; diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index d2f78ddb04..b424362bfc 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -131,7 +131,11 @@ def get_google_drive_object(g_drive): return google_drive_object, account -def create_folder_in_google_drive(google_drive_object, account): +@frappe.whitelist() +def create_folder_in_google_drive(google_drive_object=None, account=None, g_drive=None): + if g_drive: + google_drive_object, account = get_google_drive_object(g_drive) + file_metadata = { "name": account.backup_folder_name, "mimeType": "application/vnd.google-apps.folder" @@ -139,6 +143,8 @@ def create_folder_in_google_drive(google_drive_object, account): folder = google_drive_object.files().create(body=file_metadata, fields="id").execute() frappe.db.set_value("Google Drive", account.name, "backup_folder_id", folder.get("id")) + return "Folder created successfully in Google Drive." + def check_for_folder_in_google_drive(google_drive_object, account): """ Create a folder on Drive, returns the newely created folders ID From 6fecd28df04bfa09e6be52ce3edd7c0a9b10a584 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 11 Aug 2019 19:48:16 +0530 Subject: [PATCH 10/58] fix: show drive id --- frappe/integrations/doctype/google_drive/google_drive.js | 2 ++ frappe/integrations/doctype/google_drive/google_drive.json | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.js b/frappe/integrations/doctype/google_drive/google_drive.js index d37ac23a48..b8bf2f9f3d 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.js +++ b/frappe/integrations/doctype/google_drive/google_drive.js @@ -40,6 +40,8 @@ frappe.ui.form.on('Google Drive', { frappe.msgprint(r.message); }); }); + } else { + frm.set_df_property("backup_folder_id", "read_only", 1); } }, authorize_google_drive_access: function(frm) { diff --git a/frappe/integrations/doctype/google_drive/google_drive.json b/frappe/integrations/doctype/google_drive/google_drive.json index 2f25381173..d10e86bab1 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.json +++ b/frappe/integrations/doctype/google_drive/google_drive.json @@ -83,11 +83,10 @@ { "fieldname": "backup_folder_id", "fieldtype": "Data", - "label": "Backup Folder ID", - "read_only": 1 + "label": "Backup Folder ID" } ], - "modified": "2019-08-11 16:00:39.521237", + "modified": "2019-08-11 16:17:26.314299", "modified_by": "Administrator", "module": "Integrations", "name": "Google Drive", From cd732c36b7b49e0b17780d26a4301804f9bfaecc Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 11 Aug 2019 19:52:22 +0530 Subject: [PATCH 11/58] fix: refresh page --- frappe/integrations/doctype/google_drive/google_drive.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.js b/frappe/integrations/doctype/google_drive/google_drive.js index b8bf2f9f3d..42e46281e1 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.js +++ b/frappe/integrations/doctype/google_drive/google_drive.js @@ -24,7 +24,7 @@ frappe.ui.form.on('Google Drive', { }); }); } - if (!frm.doc.backup_folder_id) { + if (!frm.doc.backup_folder_id && frm.doc.refresh_token) { let sync_button = frm.add_custom_button(__("Create Folder in Google Drive"), function () { frappe.show_alert({ indicator: "green", @@ -37,6 +37,7 @@ frappe.ui.form.on('Google Drive', { }, btn: sync_button }).then((r) => { + frm.refresh(); frappe.msgprint(r.message); }); }); From b4bff26f3f937079971f4dab660813a28409380e Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 11 Aug 2019 20:00:03 +0530 Subject: [PATCH 12/58] fix: show proper feedback --- frappe/integrations/doctype/google_drive/google_drive.py | 4 +++- frappe/public/js/frappe/form/print.js | 7 ++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index b424362bfc..673d279384 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -198,6 +198,8 @@ def upload_document_to_google_drive(doctype, docname, g_drive, format, letterhea except HttpError as e: frappe.msgprint(_("Google Drive - Could not upload file - Error Code {0}").format(e)) + return _("{0} {1} uploaded to Google Drive successfully.").format(doctype, docname) + @frappe.whitelist() def upload_system_backup_to_google_drive(g_drive): """ @@ -226,7 +228,7 @@ def upload_system_backup_to_google_drive(g_drive): except HttpError as e: frappe.msgprint(_("Google Drive - Could not upload backup - Error {0}").format(e)) - return "Google Drive Backup Successful." + return _("Google Drive Backup Successful.") def daily_backup(): g_drive = frappe.db.exists("Google Drive", {"enable": 1, "enable_system_backup": 1, "frequency": "Daily"}) diff --git a/frappe/public/js/frappe/form/print.js b/frappe/public/js/frappe/form/print.js index 855e851b0f..89556e1d62 100644 --- a/frappe/public/js/frappe/form/print.js +++ b/frappe/public/js/frappe/form/print.js @@ -497,11 +497,8 @@ frappe.ui.form.PrintPreview = Class.extend({ format: me.selected_format(), letterhead: me.with_letterhead() ? "0" : "1" }, - callback: function() { - frappe.show_alert({ - indicator: "green", - message: __("Document uploaded to Google Drive.") - }); + callback: function(r) { + frappe.msgprint(r.message); } }) } From ed994eaf9195857511557df8e0dd5b8a37488c6c Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 11 Aug 2019 23:24:00 +0530 Subject: [PATCH 13/58] fix: frappe throw if folder not synced --- frappe/integrations/doctype/google_drive/google_drive.js | 3 ++- frappe/integrations/doctype/google_drive/google_drive.py | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.js b/frappe/integrations/doctype/google_drive/google_drive.js index 42e46281e1..9e4c8e3009 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.js +++ b/frappe/integrations/doctype/google_drive/google_drive.js @@ -24,6 +24,7 @@ frappe.ui.form.on('Google Drive', { }); }); } + if (!frm.doc.backup_folder_id && frm.doc.refresh_token) { let sync_button = frm.add_custom_button(__("Create Folder in Google Drive"), function () { frappe.show_alert({ @@ -37,7 +38,7 @@ frappe.ui.form.on('Google Drive', { }, btn: sync_button }).then((r) => { - frm.refresh(); + refresh_field("backup_folder_id"); frappe.msgprint(r.message); }); }); diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index 673d279384..09ea54feab 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -117,6 +117,9 @@ def get_google_drive_object(g_drive): google_settings = frappe.get_doc("Google Settings") account = frappe.get_doc("Google Drive", g_drive) + if not account.backup_folder_id: + frappe.throw(_("Folder {0} not created in Google Drive.").format(account.backup_folder_name)) + credentials_dict = { "token": account.get_access_token(), "refresh_token": account.get_password(fieldname="refresh_token", raise_exception=False), From 184ee4ed5aa7839108f98b7c22dd4aff3337cb51 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Sun, 11 Aug 2019 23:41:23 +0530 Subject: [PATCH 14/58] fix: msgrint --- .../integrations/doctype/google_drive/google_drive.json | 6 +++--- frappe/public/js/frappe/form/print.js | 9 +++++---- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.json b/frappe/integrations/doctype/google_drive/google_drive.json index d10e86bab1..398b96f817 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.json +++ b/frappe/integrations/doctype/google_drive/google_drive.json @@ -45,13 +45,13 @@ }, { "fieldname": "authorization_code", - "fieldtype": "Password", + "fieldtype": "Data", "hidden": 1, "label": "Authorization Code" }, { "fieldname": "refresh_token", - "fieldtype": "Password", + "fieldtype": "Data", "hidden": 1, "label": "Refresh Token" }, @@ -86,7 +86,7 @@ "label": "Backup Folder ID" } ], - "modified": "2019-08-11 16:17:26.314299", + "modified": "2019-08-11 20:08:45.407321", "modified_by": "Administrator", "module": "Integrations", "name": "Google Drive", diff --git a/frappe/public/js/frappe/form/print.js b/frappe/public/js/frappe/form/print.js index 89556e1d62..5e4e3e5816 100644 --- a/frappe/public/js/frappe/form/print.js +++ b/frappe/public/js/frappe/form/print.js @@ -479,15 +479,15 @@ frappe.ui.form.PrintPreview = Class.extend({ ], primary_action_label: __("Submit"), primary_action: (d) => { + uploader.hide(); + uploader.disable_primary_action(); + uploader.clear(); + frappe.show_alert({ indicator: "red", message: __("Uploading to Google Drive.") }) - uploader.hide(); - uploader.disable_primary_action(); - uploader.clear(); - frappe.call({ method: "frappe.integrations.doctype.google_drive.google_drive.upload_document_to_google_drive", args: { @@ -499,6 +499,7 @@ frappe.ui.form.PrintPreview = Class.extend({ }, callback: function(r) { frappe.msgprint(r.message); + uploader.enable_primary_action(); } }) } From 097a366f2851c630e1a89473d00acefef074eb8a Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 12 Aug 2019 09:05:34 +0530 Subject: [PATCH 15/58] fix: show alerts while uploading --- .../doctype/google_drive/google_drive.py | 6 +++++- frappe/public/js/frappe/form/print.js | 13 ++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index 09ea54feab..c87be2317a 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -197,11 +197,12 @@ def upload_document_to_google_drive(doctype, docname, g_drive, format, letterhea media = MediaFileUpload(get_absolute_path(fileurl), mimetype="application/pdf", resumable=True) try: + display_upload_status("orange", _("Uploading file to Google Drive.")) google_drive_object.files().create(body=file_metadata, media_body=media, fields="id").execute() except HttpError as e: frappe.msgprint(_("Google Drive - Could not upload file - Error Code {0}").format(e)) - return _("{0} {1} uploaded to Google Drive successfully.").format(doctype, docname) + display_upload_status("green", _("File Uploaded to Google Drive.")) @frappe.whitelist() def upload_system_backup_to_google_drive(g_drive): @@ -233,6 +234,9 @@ def upload_system_backup_to_google_drive(g_drive): return _("Google Drive Backup Successful.") +def display_upload_status(indicator, message): + frappe.publish_realtime("upload_google_drive", dict(indicator=indicator, message=message), user=frappe.session.user) + def daily_backup(): g_drive = frappe.db.exists("Google Drive", {"enable": 1, "enable_system_backup": 1, "frequency": "Daily"}) if g_drive: diff --git a/frappe/public/js/frappe/form/print.js b/frappe/public/js/frappe/form/print.js index 5e4e3e5816..6a650971ca 100644 --- a/frappe/public/js/frappe/form/print.js +++ b/frappe/public/js/frappe/form/print.js @@ -457,6 +457,14 @@ frappe.ui.form.PrintPreview = Class.extend({ }, google_drive_upload: function() { var me = this; + + frappe.realtime.on("upload_google_drive", (data) => { + frappe.show_alert({ + indicator: data.indicator, + message: data.message + }); + }); + this.wrapper.find(".btn-upload-drive").click(function () { let uploader = new frappe.ui.Dialog({ title: __("Upload File to Google Drive"), @@ -485,8 +493,8 @@ frappe.ui.form.PrintPreview = Class.extend({ frappe.show_alert({ indicator: "red", - message: __("Uploading to Google Drive.") - }) + message: __("Preparing file to upload.") + }); frappe.call({ method: "frappe.integrations.doctype.google_drive.google_drive.upload_document_to_google_drive", @@ -498,7 +506,6 @@ frappe.ui.form.PrintPreview = Class.extend({ letterhead: me.with_letterhead() ? "0" : "1" }, callback: function(r) { - frappe.msgprint(r.message); uploader.enable_primary_action(); } }) From db3656afb7b9e734a117a0f41701632a2571b8e9 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 12 Aug 2019 09:46:51 +0530 Subject: [PATCH 16/58] fix: codacy fixes --- frappe/boot.py | 4 ---- .../doctype/google_drive/google_drive.js | 4 ++-- .../doctype/google_drive/google_drive.py | 16 ++++++++-------- frappe/public/build.json | 2 -- frappe/public/js/frappe/form/print.js | 3 ++- frappe/public/js/integrations/gsuite.js | 15 --------------- 6 files changed, 12 insertions(+), 32 deletions(-) delete mode 100644 frappe/public/js/integrations/gsuite.js diff --git a/frappe/boot.py b/frappe/boot.py index 60c5e17cd4..d0fa0f2c71 100644 --- a/frappe/boot.py +++ b/frappe/boot.py @@ -76,7 +76,6 @@ def get_bootinfo(): bootinfo.calendars = sorted(frappe.get_hooks("calendars")) bootinfo.treeviews = frappe.get_hooks("treeviews") or [] bootinfo.lang_dict = get_lang_dict() - bootinfo.google_drive_enabled = get_google_drive_status() bootinfo.success_action = get_success_action() bootinfo.update(get_email_accounts(user=frappe.session.user)) bootinfo.energy_points_enabled = is_energy_point_enabled() @@ -258,9 +257,6 @@ def get_unseen_notes(): (select user from `tabNote Seen By` nsb where nsb.parent=`tabNote`.name)''', (frappe.utils.now(), frappe.session.user), as_dict=True) -def get_google_drive_status(): - return True if frappe.db.exists("Google Drive", {"enable": 1}) else False - def get_success_action(): return frappe.get_all("Success Action", fields=["*"]) diff --git a/frappe/integrations/doctype/google_drive/google_drive.js b/frappe/integrations/doctype/google_drive/google_drive.js index 9e4c8e3009..879c6eed89 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.js +++ b/frappe/integrations/doctype/google_drive/google_drive.js @@ -48,7 +48,7 @@ frappe.ui.form.on('Google Drive', { }, authorize_google_drive_access: function(frm) { let reauthorize = 0; - if(frm.doc.authorization_code) { + if (frm.doc.authorization_code) { reauthorize = 1; } @@ -59,7 +59,7 @@ frappe.ui.form.on('Google Drive', { "reauthorize": reauthorize }, callback: function(r) { - if(!r.exc) { + if (!r.exc) { frm.save(); window.open(r.message.url); } diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index c87be2317a..62d3d507b8 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -15,7 +15,7 @@ from frappe.model.document import Document from frappe.utils import get_request_site_address from six.moves.urllib.parse import quote from apiclient.http import MediaFileUpload -from frappe.utils.file_manager import save_file, get_file_url +from frappe.utils.file_manager import save_file from frappe.utils.print_format import download_pdf from frappe.utils import get_backups_path, get_files_path from frappe.utils.backups import new_backup @@ -143,8 +143,11 @@ def create_folder_in_google_drive(google_drive_object=None, account=None, g_driv "name": account.backup_folder_name, "mimeType": "application/vnd.google-apps.folder" } - folder = google_drive_object.files().create(body=file_metadata, fields="id").execute() - frappe.db.set_value("Google Drive", account.name, "backup_folder_id", folder.get("id")) + try: + folder = google_drive_object.files().create(body=file_metadata, fields="id").execute() + frappe.db.set_value("Google Drive", account.name, "backup_folder_id", folder.get("id")) + except HttpError as e + frappe.throw(_("Google Drive - Could not create folder in Google Drive - Error Code {0}").format(e)) return "Folder created successfully in Google Drive." @@ -157,12 +160,9 @@ def check_for_folder_in_google_drive(google_drive_object, account): return try: - folder = google_drive_object.files().get(fileId=account.backup_folder_id, fields="id").execute() + google_drive_object.files().get(fileId=account.backup_folder_id, fields="id").execute() except HttpError as e: - if e.resp.status == 404: - create_folder_in_google_drive(google_drive_object, account) - else: - frappe.msgprint(_("Google Drive - Could not create folder - Error Code {0}.").format(e)) + frappe.throw(_("Google Drive - Could not find folder in Google Drive - Error Code {0}.").format(e)) @frappe.whitelist() def upload_document_to_google_drive(doctype, docname, g_drive, format, letterhead): diff --git a/frappe/public/build.json b/frappe/public/build.json index 7bec259933..5e55e3e1f8 100755 --- a/frappe/public/build.json +++ b/frappe/public/build.json @@ -187,7 +187,6 @@ "public/js/frappe/ui/upload.html", "public/js/frappe/upload.js", - "public/js/integrations/gsuite.js", "public/js/frappe/ui/tree.js", "public/js/frappe/views/container.js", @@ -205,7 +204,6 @@ "public/js/frappe/ui/toolbar/toolbar.js", "public/js/frappe/ui/toolbar/notifications.js", "public/js/frappe/views/communication.js", - "public/js/frappe/views/google_drive_uploader.js", "public/js/frappe/views/translation_manager.js", "public/js/frappe/ui/sort_selector.html", diff --git a/frappe/public/js/frappe/form/print.js b/frappe/public/js/frappe/form/print.js index 6a650971ca..6030219412 100644 --- a/frappe/public/js/frappe/form/print.js +++ b/frappe/public/js/frappe/form/print.js @@ -506,9 +506,10 @@ frappe.ui.form.PrintPreview = Class.extend({ letterhead: me.with_letterhead() ? "0" : "1" }, callback: function(r) { + frappe.msgprint(r.message); uploader.enable_primary_action(); } - }) + }); } }); uploader.show(); diff --git a/frappe/public/js/integrations/gsuite.js b/frappe/public/js/integrations/gsuite.js deleted file mode 100644 index 53248a8f32..0000000000 --- a/frappe/public/js/integrations/gsuite.js +++ /dev/null @@ -1,15 +0,0 @@ -frappe.provide("frappe.integration_service"); - -frappe.integration_service.gsuite = { - create_gsuite_file: function(args, opts) { - return frappe.call({ - type:'POST', - method: 'frappe.integrations.doctype.gsuite_templates.gsuite_templates.create_gsuite_doc', - args: args, - callback: function(r) { - var attachment = r.message; - opts.callback && opts.callback(attachment, r); - } - }); - } -}; From d9103614738de7c3604fd2719cfe5e9eb4bda88d Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 12 Aug 2019 10:25:21 +0530 Subject: [PATCH 17/58] fix: get auth url from google settings --- .../doctype/google_calendar/google_calendar.py | 7 ++++--- .../doctype/google_contacts/google_contacts.py | 5 +++-- .../doctype/google_drive/google_drive.py | 13 +++++++------ .../doctype/google_settings/google_settings.py | 5 ++++- 4 files changed, 18 insertions(+), 12 deletions(-) diff --git a/frappe/integrations/doctype/google_calendar/google_calendar.py b/frappe/integrations/doctype/google_calendar/google_calendar.py index cc503db9f7..d6ba82ed5a 100644 --- a/frappe/integrations/doctype/google_calendar/google_calendar.py +++ b/frappe/integrations/doctype/google_calendar/google_calendar.py @@ -16,6 +16,7 @@ from frappe.utils import add_days, get_datetime, get_weekdays, now_datetime, add from dateutil import parser from datetime import datetime, timedelta from six.moves.urllib.parse import quote +from frappe.integrations.doctype.google_settings.google_settings import get_auth_url SCOPES = "https://www.googleapis.com/auth/calendar" @@ -81,7 +82,7 @@ class GoogleCalendar(Document): } try: - r = requests.post("https://www.googleapis.com/oauth2/v4/token", data=data).json() + r = requests.post(get_auth_url(), data=data).json() except requests.exceptions.HTTPError: button_label = frappe.bold(_("Allow Google Calendar Access")) frappe.throw(_("Something went wrong during the token generation. Click on {0} to generate a new one.").format(button_label)) @@ -111,7 +112,7 @@ def authorize_access(g_calendar, reauthorize=None): "redirect_uri": redirect_uri, "grant_type": "authorization_code" } - r = requests.post("https://www.googleapis.com/oauth2/v4/token", data=data).json() + r = requests.post(get_auth_url(), data=data).json() if "refresh_token" in r: frappe.db.set_value("Google Calendar", google_calendar.name, "refresh_token", r.get("refresh_token")) @@ -162,7 +163,7 @@ def get_google_calendar_object(g_calendar): credentials_dict = { "token": account.get_access_token(), "refresh_token": account.get_password(fieldname="refresh_token", raise_exception=False), - "token_uri": "https://www.googleapis.com/oauth2/v4/token", + "token_uri": get_auth_url(), "client_id": google_settings.client_id, "client_secret": google_settings.get_password(fieldname="client_secret", raise_exception=False), "scopes": "https://www.googleapis.com/auth/calendar/v3" diff --git a/frappe/integrations/doctype/google_contacts/google_contacts.py b/frappe/integrations/doctype/google_contacts/google_contacts.py index 6610173e3e..e7eaf928d1 100644 --- a/frappe/integrations/doctype/google_contacts/google_contacts.py +++ b/frappe/integrations/doctype/google_contacts/google_contacts.py @@ -8,6 +8,7 @@ import requests from frappe.model.document import Document from frappe import _ from frappe.utils import get_request_site_address +from frappe.integrations.doctype.google_settings.google_settings import get_auth_url SCOPES = "https://www.googleapis.com/auth/contacts" REQUEST = "https://people.googleapis.com/v1/people/me/connections" @@ -38,7 +39,7 @@ class GoogleContacts(Document): } try: - r = requests.post("https://www.googleapis.com/oauth2/v4/token", data=data).json() + r = requests.post(get_auth_url(), data=data).json() except requests.exceptions.HTTPError: button_label = frappe.bold(_('Allow Google Contacts Access')) frappe.throw(_("Something went wrong during the token generation. Click on {0} to generate a new one.").format(button_label)) @@ -69,7 +70,7 @@ def authorize_access(g_contact, reauthorize=None): "redirect_uri": redirect_uri, "grant_type": "authorization_code" } - r = requests.post("https://www.googleapis.com/oauth2/v4/token", data=data).json() + r = requests.post(get_auth_url(), data=data).json() if "refresh_token" in r: frappe.db.set_value("Google Contacts", google_contact.name, "refresh_token", r.get("refresh_token")) diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index 62d3d507b8..ca4b00abf6 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -20,8 +20,9 @@ from frappe.utils.print_format import download_pdf from frappe.utils import get_backups_path, get_files_path from frappe.utils.backups import new_backup from frappe.utils import now +from frappe.integrations.doctype.google_settings.google_settings import get_auth_url -SCOPES = "https://www.googleapis.com/auth/drive" +SCOPES = "https://www.googleapis.com/auth/drive/v3" class GoogleDrive(Document): @@ -50,7 +51,7 @@ class GoogleDrive(Document): } try: - r = requests.post("https://www.googleapis.com/oauth2/v4/token", data=data).json() + r = requests.post(get_auth_url(), data=data).json() except requests.exceptions.HTTPError: button_label = frappe.bold(_("Allow Google Drive Access")) frappe.throw(_("Something went wrong during the token generation. Click on {0} to generate a new one.").format(button_label)) @@ -81,7 +82,7 @@ def authorize_access(g_drive, reauthorize=None): "redirect_uri": redirect_uri, "grant_type": "authorization_code" } - r = requests.post("https://www.googleapis.com/oauth2/v4/token", data=data).json() + r = requests.post(get_auth_url(), data=data).json() if "refresh_token" in r: frappe.db.set_value("Google Drive", google_drive.name, "refresh_token", r.get("refresh_token")) @@ -123,10 +124,10 @@ def get_google_drive_object(g_drive): credentials_dict = { "token": account.get_access_token(), "refresh_token": account.get_password(fieldname="refresh_token", raise_exception=False), - "token_uri": "https://www.googleapis.com/oauth2/v4/token", + "token_uri": get_auth_url(), "client_id": google_settings.client_id, "client_secret": google_settings.get_password(fieldname="client_secret", raise_exception=False), - "scopes": "https://www.googleapis.com/auth/drive/v3" + "scopes": SCOPES } credentials = google.oauth2.credentials.Credentials(**credentials_dict) @@ -146,7 +147,7 @@ def create_folder_in_google_drive(google_drive_object=None, account=None, g_driv try: folder = google_drive_object.files().create(body=file_metadata, fields="id").execute() frappe.db.set_value("Google Drive", account.name, "backup_folder_id", folder.get("id")) - except HttpError as e + except HttpError as e: frappe.throw(_("Google Drive - Could not create folder in Google Drive - Error Code {0}").format(e)) return "Folder created successfully in Google Drive." diff --git a/frappe/integrations/doctype/google_settings/google_settings.py b/frappe/integrations/doctype/google_settings/google_settings.py index 50713f187c..ecc975235a 100644 --- a/frappe/integrations/doctype/google_settings/google_settings.py +++ b/frappe/integrations/doctype/google_settings/google_settings.py @@ -7,4 +7,7 @@ from __future__ import unicode_literals from frappe.model.document import Document class GoogleSettings(Document): - pass \ No newline at end of file + pass + +def get_auth_url(): + return "https://www.googleapis.com/oauth2/v4/token" \ No newline at end of file From 468735adf93c02f2090e35952a8a4a8dc9d0aefb Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 12 Aug 2019 11:04:23 +0530 Subject: [PATCH 18/58] chore: codacy fixes --- .../doctype/google_drive/google_drive.py | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index ca4b00abf6..0a055ab47e 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -17,7 +17,7 @@ from six.moves.urllib.parse import quote from apiclient.http import MediaFileUpload from frappe.utils.file_manager import save_file from frappe.utils.print_format import download_pdf -from frappe.utils import get_backups_path, get_files_path +from frappe.utils import get_backups_path, get_files_path, get_bench_path from frappe.utils.backups import new_backup from frappe.utils import now from frappe.integrations.doctype.google_settings.google_settings import get_auth_url @@ -131,37 +131,37 @@ def get_google_drive_object(g_drive): } credentials = google.oauth2.credentials.Credentials(**credentials_dict) - google_drive_object = googleapiclient.discovery.build("drive", "v3", credentials=credentials) + google_drive = googleapiclient.discovery.build("drive", "v3", credentials=credentials) - return google_drive_object, account + return google_drive, account @frappe.whitelist() -def create_folder_in_google_drive(google_drive_object=None, account=None, g_drive=None): +def create_folder_in_google_drive(google_drive=None, account=None, g_drive=None): if g_drive: - google_drive_object, account = get_google_drive_object(g_drive) + google_drive, account = get_google_drive_object(g_drive) file_metadata = { "name": account.backup_folder_name, "mimeType": "application/vnd.google-apps.folder" } try: - folder = google_drive_object.files().create(body=file_metadata, fields="id").execute() + folder = google_drive.files().create(body=file_metadata, fields="id").execute() frappe.db.set_value("Google Drive", account.name, "backup_folder_id", folder.get("id")) except HttpError as e: frappe.throw(_("Google Drive - Could not create folder in Google Drive - Error Code {0}").format(e)) return "Folder created successfully in Google Drive." -def check_for_folder_in_google_drive(google_drive_object, account): +def check_for_folder_in_google_drive(google_drive, account): """ Create a folder on Drive, returns the newely created folders ID """ if not account.backup_folder_id: - create_folder_in_google_drive(google_drive_object, account) + create_folder_in_google_drive(google_drive, account) return try: - google_drive_object.files().get(fileId=account.backup_folder_id, fields="id").execute() + google_drive.files().get(fileId=account.backup_folder_id, fields="id").execute() except HttpError as e: frappe.throw(_("Google Drive - Could not find folder in Google Drive - Error Code {0}.").format(e)) @@ -171,10 +171,10 @@ def upload_document_to_google_drive(doctype, docname, g_drive, format, letterhea Uploads Document to Folder specified in Google Drive Doc. """ # Get Google Drive Object - google_drive_object, account = get_google_drive_object(g_drive) + google_drive, account = get_google_drive_object(g_drive) # Check if folder exists in Google Drive - check_for_folder_in_google_drive(google_drive_object, account) + check_for_folder_in_google_drive(google_drive, account) account.load_from_db() # Create PDF for doc and append datestring to name @@ -199,7 +199,7 @@ def upload_document_to_google_drive(doctype, docname, g_drive, format, letterhea try: display_upload_status("orange", _("Uploading file to Google Drive.")) - google_drive_object.files().create(body=file_metadata, media_body=media, fields="id").execute() + google_drive.files().create(body=file_metadata, media_body=media, fields="id").execute() except HttpError as e: frappe.msgprint(_("Google Drive - Could not upload file - Error Code {0}").format(e)) @@ -211,10 +211,10 @@ def upload_system_backup_to_google_drive(g_drive): Upload system backup to Google Drive """ # Get Google Drive Object - google_drive_object, account = get_google_drive_object(g_drive) + google_drive, account = get_google_drive_object(g_drive) # Check if folder exists in Google Drive - check_for_folder_in_google_drive(google_drive_object, account) + check_for_folder_in_google_drive(google_drive, account) account.load_from_db() backup = new_backup(ignore_files=True) @@ -229,7 +229,7 @@ def upload_system_backup_to_google_drive(g_drive): media = MediaFileUpload(get_absolute_path(fileurl, True), mimetype="application/gzip", resumable=True) try: - google_drive_object.files().create(body=file_metadata, media_body=media, fields="id").execute() + google_drive.files().create(body=file_metadata, media_body=media, fields="id").execute() except HttpError as e: frappe.msgprint(_("Google Drive - Could not upload backup - Error {0}").format(e)) @@ -249,9 +249,9 @@ def weekly_backup(): upload_system_backup_to_google_drive(g_drive) def get_absolute_path(filename, backup=False): - file_path = os.path.join(frappe.utils.get_files_path()[2:], filename) + file_path = os.path.join(get_files_path()[2:], filename) if backup: - file_path = os.path.join(frappe.utils.get_backups_path()[2:], filename) + file_path = os.path.join(get_backups_path()[2:], filename) - return "{0}/sites/{1}".format(frappe.utils.get_bench_path(), file_path) \ No newline at end of file + return "{0}/sites/{1}".format(get_bench_path(), file_path) \ No newline at end of file From c4d65de32aca91d3bab26f67f8efc4775cddc49e Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 12 Aug 2019 17:26:40 +0530 Subject: [PATCH 19/58] chore: rename to avoid same name as builtin --- frappe/integrations/doctype/google_drive/google_drive.py | 2 +- frappe/public/js/frappe/form/print.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index 0a055ab47e..64f43e9fc5 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -166,7 +166,7 @@ def check_for_folder_in_google_drive(google_drive, account): frappe.throw(_("Google Drive - Could not find folder in Google Drive - Error Code {0}.").format(e)) @frappe.whitelist() -def upload_document_to_google_drive(doctype, docname, g_drive, format, letterhead): +def upload_doc_to_google_drive(doctype, docname, g_drive, format, letterhead): """ Uploads Document to Folder specified in Google Drive Doc. """ diff --git a/frappe/public/js/frappe/form/print.js b/frappe/public/js/frappe/form/print.js index 6030219412..891ea3ada5 100644 --- a/frappe/public/js/frappe/form/print.js +++ b/frappe/public/js/frappe/form/print.js @@ -497,7 +497,7 @@ frappe.ui.form.PrintPreview = Class.extend({ }); frappe.call({ - method: "frappe.integrations.doctype.google_drive.google_drive.upload_document_to_google_drive", + method: "frappe.integrations.doctype.google_drive.google_drive.upload_doc_to_google_drive", args: { doctype: me.frm.doc.doctype, docname: me.frm.doc.name, From a4fe2b6b7c4facfff5d7f29e26243ec3843779f7 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Tue, 13 Aug 2019 17:50:54 +0530 Subject: [PATCH 20/58] fix: remove pdf upload functionality --- .../doctype/google_drive/google_drive.json | 61 +++++++++--------- .../doctype/google_drive/google_drive.py | 54 ++-------------- frappe/public/js/frappe/form/print.js | 62 ------------------- .../frappe/form/templates/print_layout.html | 2 - 4 files changed, 38 insertions(+), 141 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.json b/frappe/integrations/doctype/google_drive/google_drive.json index 398b96f817..8b778f9b90 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.json +++ b/frappe/integrations/doctype/google_drive/google_drive.json @@ -1,6 +1,6 @@ { "autoname": "field:backup_folder_name", - "creation": "2019-08-08 13:16:06.783138", + "creation": "2019-08-13 17:24:05.470876", "doctype": "DocType", "engine": "InnoDB", "field_order": [ @@ -9,6 +9,7 @@ "user", "backup_folder_name", "authorize_google_drive_access", + "last_backup_on", "column_break_5", "backup_folder_id", "enable_system_backup", @@ -37,28 +38,34 @@ "options": "User", "reqd": 1 }, + { + "fieldname": "backup_folder_name", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Backup Folder Name", + "set_only_once": 1 + }, { "depends_on": "eval:!doc.__islocal", "fieldname": "authorize_google_drive_access", "fieldtype": "Button", "label": "Authorize Google Drive Access" }, - { - "fieldname": "authorization_code", - "fieldtype": "Data", - "hidden": 1, - "label": "Authorization Code" - }, - { - "fieldname": "refresh_token", - "fieldtype": "Data", - "hidden": 1, - "label": "Refresh Token" - }, { "fieldname": "column_break_5", "fieldtype": "Column Break" }, + { + "fieldname": "backup_folder_id", + "fieldtype": "Data", + "label": "Backup Folder ID" + }, + { + "default": "0", + "fieldname": "enable_system_backup", + "fieldtype": "Check", + "label": "Enable System Backup" + }, { "depends_on": "enable_system_backup", "fieldname": "frequency", @@ -67,26 +74,26 @@ "options": "Daily\nWeekly" }, { - "default": "0", - "fieldname": "enable_system_backup", - "fieldtype": "Check", - "label": "Enable System Backup" + "fieldname": "refresh_token", + "fieldtype": "Data", + "hidden": 1, + "label": "Refresh Token" }, { - "fieldname": "backup_folder_name", + "fieldname": "authorization_code", "fieldtype": "Data", - "in_list_view": 1, - "label": "Backup Folder Name", - "set_only_once": 1, - "unique": 1 + "hidden": 1, + "label": "Authorization Code" }, { - "fieldname": "backup_folder_id", - "fieldtype": "Data", - "label": "Backup Folder ID" + "fieldname": "last_backup_on", + "fieldtype": "Datetime", + "label": "Last Backup On", + "read_only": 1 } ], - "modified": "2019-08-11 20:08:45.407321", + "issingle": 1, + "modified": "2019-08-13 17:36:13.014410", "modified_by": "Administrator", "module": "Integrations", "name": "Google Drive", @@ -106,10 +113,8 @@ "create": 1, "delete": 1, "email": 1, - "export": 1, "print": 1, "read": 1, - "report": 1, "role": "All", "share": 1, "write": 1 diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index 64f43e9fc5..83d69c6645 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -66,12 +66,11 @@ def authorize_access(g_drive, reauthorize=None): """ google_settings = frappe.get_doc("Google Settings") - google_drive = frappe.get_doc("Google Drive", g_drive) + google_drive = frappe.get_doc("Google Drive") redirect_uri = get_request_site_address(True) + "?cmd=frappe.integrations.doctype.google_drive.google_drive.google_callback" if not google_drive.authorization_code or reauthorize: - frappe.cache().hset("google_drive", "google_drive", google_drive.name) return get_authentication_url(client_id=google_settings.client_id, redirect_uri=redirect_uri) else: try: @@ -89,7 +88,7 @@ def authorize_access(g_drive, reauthorize=None): frappe.db.commit() frappe.local.response["type"] = "redirect" - frappe.local.response["location"] = "/desk#Form/{0}/{1}".format(quote("Google Drive"), quote(google_drive.name)) + frappe.local.response["location"] = "/desk#Form/{0}".format(quote("Google Drive")) frappe.msgprint(_("Google Drive has been configured.")) except Exception as e: @@ -105,8 +104,7 @@ def google_callback(code=None): """ Authorization code is sent to callback as per the API configuration """ - google_drive = frappe.cache().hget("google_drive", "google_drive") - frappe.db.set_value("Google Drive", google_drive, "authorization_code", code) + frappe.db.set_value("Google Drive", None, "authorization_code", code) frappe.db.commit() authorize_access(google_drive) @@ -146,7 +144,7 @@ def create_folder_in_google_drive(google_drive=None, account=None, g_drive=None) } try: folder = google_drive.files().create(body=file_metadata, fields="id").execute() - frappe.db.set_value("Google Drive", account.name, "backup_folder_id", folder.get("id")) + frappe.db.set_value("Google Drive", None, "backup_folder_id", folder.get("id")) except HttpError as e: frappe.throw(_("Google Drive - Could not create folder in Google Drive - Error Code {0}").format(e)) @@ -165,46 +163,6 @@ def check_for_folder_in_google_drive(google_drive, account): except HttpError as e: frappe.throw(_("Google Drive - Could not find folder in Google Drive - Error Code {0}.").format(e)) -@frappe.whitelist() -def upload_doc_to_google_drive(doctype, docname, g_drive, format, letterhead): - """ - Uploads Document to Folder specified in Google Drive Doc. - """ - # Get Google Drive Object - google_drive, account = get_google_drive_object(g_drive) - - # Check if folder exists in Google Drive - check_for_folder_in_google_drive(google_drive, account) - account.load_from_db() - - # Create PDF for doc and append datestring to name - download_pdf(doctype=doctype, name=docname, format=format, no_letterhead=letterhead) - filename = frappe.local.response.filename.replace(".pdf", "-{0}.pdf".format(now())) - filecontent = frappe.local.response.filecontent - - file_to_upload = save_file(filename, filecontent, doctype, docname) - - if not file_to_upload: - frappe.throw(_("Could not upload pdf to Google Drive")) - - fileurl = os.path.basename(file_to_upload.file_name or file_to_upload.file_url) - - # parents: Folder id under which the file is to be uploaded - file_metadata = { - "name": filename, - "parents": [account.backup_folder_id] - } - - media = MediaFileUpload(get_absolute_path(fileurl), mimetype="application/pdf", resumable=True) - - try: - display_upload_status("orange", _("Uploading file to Google Drive.")) - google_drive.files().create(body=file_metadata, media_body=media, fields="id").execute() - except HttpError as e: - frappe.msgprint(_("Google Drive - Could not upload file - Error Code {0}").format(e)) - - display_upload_status("green", _("File Uploaded to Google Drive.")) - @frappe.whitelist() def upload_system_backup_to_google_drive(g_drive): """ @@ -230,14 +188,12 @@ def upload_system_backup_to_google_drive(g_drive): try: google_drive.files().create(body=file_metadata, media_body=media, fields="id").execute() + frappe.db.set_value("Google Drive", None, "last_backup_on", frappe.utils.now_datetime()) except HttpError as e: frappe.msgprint(_("Google Drive - Could not upload backup - Error {0}").format(e)) return _("Google Drive Backup Successful.") -def display_upload_status(indicator, message): - frappe.publish_realtime("upload_google_drive", dict(indicator=indicator, message=message), user=frappe.session.user) - def daily_backup(): g_drive = frappe.db.exists("Google Drive", {"enable": 1, "enable_system_backup": 1, "frequency": "Daily"}) if g_drive: diff --git a/frappe/public/js/frappe/form/print.js b/frappe/public/js/frappe/form/print.js index 891ea3ada5..ec78b30c8a 100644 --- a/frappe/public/js/frappe/form/print.js +++ b/frappe/public/js/frappe/form/print.js @@ -146,8 +146,6 @@ frappe.ui.form.PrintPreview = Class.extend({ frappe.set_route("print-format-builder"); }, __("New Custom Print Format"), __("Start")); }); - - this.google_drive_upload(); }, setup_keyboard_shortcuts() { this.wrapper.find('.print-toolbar a.btn-default').each((i, el) => { @@ -454,66 +452,6 @@ frappe.ui.form.PrintPreview = Class.extend({ frappe.throw(__("No Printer is Available.")); } }); - }, - google_drive_upload: function() { - var me = this; - - frappe.realtime.on("upload_google_drive", (data) => { - frappe.show_alert({ - indicator: data.indicator, - message: data.message - }); - }); - - this.wrapper.find(".btn-upload-drive").click(function () { - let uploader = new frappe.ui.Dialog({ - title: __("Upload File to Google Drive"), - fields: [ - { - fieldtype: "Link", - fieldname: "google_drive", - options: "Google Drive", - label: __("Google Drive"), - reqd: 1, - get_query: function() { - return { - "filters": { - "enable": 1, - "owner": frappe.session.user, - } - } - } - } - ], - primary_action_label: __("Submit"), - primary_action: (d) => { - uploader.hide(); - uploader.disable_primary_action(); - uploader.clear(); - - frappe.show_alert({ - indicator: "red", - message: __("Preparing file to upload.") - }); - - frappe.call({ - method: "frappe.integrations.doctype.google_drive.google_drive.upload_doc_to_google_drive", - args: { - doctype: me.frm.doc.doctype, - docname: me.frm.doc.name, - g_drive: d.google_drive, - format: me.selected_format(), - letterhead: me.with_letterhead() ? "0" : "1" - }, - callback: function(r) { - frappe.msgprint(r.message); - uploader.enable_primary_action(); - } - }); - } - }); - uploader.show(); - }); } }); diff --git a/frappe/public/js/frappe/form/templates/print_layout.html b/frappe/public/js/frappe/form/templates/print_layout.html index 59f448f27f..9bdba0d99d 100644 --- a/frappe/public/js/frappe/form/templates/print_layout.html +++ b/frappe/public/js/frappe/form/templates/print_layout.html @@ -27,8 +27,6 @@ {%= __("Full Page") %} {%= __("PDF") %} - - Drive From 2b11be32c222bc91c126850499dbf55a5c1fe31b Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Tue, 13 Aug 2019 18:13:20 +0530 Subject: [PATCH 21/58] fix: codacy --- .../doctype/google_drive/google_drive.js | 21 ------------------- .../doctype/google_drive/google_drive.py | 21 +++++++------------ 2 files changed, 8 insertions(+), 34 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.js b/frappe/integrations/doctype/google_drive/google_drive.js index 879c6eed89..dd36bce026 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.js +++ b/frappe/integrations/doctype/google_drive/google_drive.js @@ -24,27 +24,6 @@ frappe.ui.form.on('Google Drive', { }); }); } - - if (!frm.doc.backup_folder_id && frm.doc.refresh_token) { - let sync_button = frm.add_custom_button(__("Create Folder in Google Drive"), function () { - frappe.show_alert({ - indicator: "green", - message: __("Creating folder in Google Drive.") - }); - frappe.call({ - method: "frappe.integrations.doctype.google_drive.google_drive.create_folder_in_google_drive", - args: { - "g_drive": frm.doc.name - }, - btn: sync_button - }).then((r) => { - refresh_field("backup_folder_id"); - frappe.msgprint(r.message); - }); - }); - } else { - frm.set_df_property("backup_folder_id", "read_only", 1); - } }, authorize_google_drive_access: function(frm) { let reauthorize = 0; diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index 83d69c6645..8e62462b52 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -15,11 +15,8 @@ from frappe.model.document import Document from frappe.utils import get_request_site_address from six.moves.urllib.parse import quote from apiclient.http import MediaFileUpload -from frappe.utils.file_manager import save_file -from frappe.utils.print_format import download_pdf from frappe.utils import get_backups_path, get_files_path, get_bench_path from frappe.utils.backups import new_backup -from frappe.utils import now from frappe.integrations.doctype.google_settings.google_settings import get_auth_url SCOPES = "https://www.googleapis.com/auth/drive/v3" @@ -109,12 +106,12 @@ def google_callback(code=None): authorize_access(google_drive) -def get_google_drive_object(g_drive): +def get_google_drive_object(): """ Returns an object of Google Drive. """ google_settings = frappe.get_doc("Google Settings") - account = frappe.get_doc("Google Drive", g_drive) + account = frappe.get_doc("Google Drive") if not account.backup_folder_id: frappe.throw(_("Folder {0} not created in Google Drive.").format(account.backup_folder_name)) @@ -133,10 +130,8 @@ def get_google_drive_object(g_drive): return google_drive, account -@frappe.whitelist() -def create_folder_in_google_drive(google_drive=None, account=None, g_drive=None): - if g_drive: - google_drive, account = get_google_drive_object(g_drive) +def create_folder_in_google_drive(google_drive, account): + google_drive, account = get_google_drive_object() file_metadata = { "name": account.backup_folder_name, @@ -164,12 +159,12 @@ def check_for_folder_in_google_drive(google_drive, account): frappe.throw(_("Google Drive - Could not find folder in Google Drive - Error Code {0}.").format(e)) @frappe.whitelist() -def upload_system_backup_to_google_drive(g_drive): +def upload_system_backup_to_google_drive(): """ Upload system backup to Google Drive """ # Get Google Drive Object - google_drive, account = get_google_drive_object(g_drive) + google_drive, account = get_google_drive_object() # Check if folder exists in Google Drive check_for_folder_in_google_drive(google_drive, account) @@ -197,12 +192,12 @@ def upload_system_backup_to_google_drive(g_drive): def daily_backup(): g_drive = frappe.db.exists("Google Drive", {"enable": 1, "enable_system_backup": 1, "frequency": "Daily"}) if g_drive: - upload_system_backup_to_google_drive(g_drive) + upload_system_backup_to_google_drive() def weekly_backup(): g_drive = frappe.db.exists("Google Drive", {"enable": 1, "enable_system_backup": 1, "frequency": "Weekly"}) if g_drive: - upload_system_backup_to_google_drive(g_drive) + upload_system_backup_to_google_drive() def get_absolute_path(filename, backup=False): file_path = os.path.join(get_files_path()[2:], filename) From 6b944cadefac160d024b65ccbbefcb90f6716df3 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Thu, 15 Aug 2019 22:22:55 +0530 Subject: [PATCH 22/58] chore: code cleanup --- .../doctype/google_drive/google_drive.js | 3 --- .../doctype/google_drive/google_drive.json | 19 +++++----------- .../doctype/google_drive/google_drive.py | 22 +++++-------------- 3 files changed, 11 insertions(+), 33 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.js b/frappe/integrations/doctype/google_drive/google_drive.js index dd36bce026..2185f9bb69 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.js +++ b/frappe/integrations/doctype/google_drive/google_drive.js @@ -15,9 +15,6 @@ frappe.ui.form.on('Google Drive', { }); frappe.call({ method: "frappe.integrations.doctype.google_drive.google_drive.upload_system_backup_to_google_drive", - args: { - "g_drive": frm.doc.name - }, btn: sync_button }).then((r) => { frappe.msgprint(r.message); diff --git a/frappe/integrations/doctype/google_drive/google_drive.json b/frappe/integrations/doctype/google_drive/google_drive.json index 8b778f9b90..2da4e6669d 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.json +++ b/frappe/integrations/doctype/google_drive/google_drive.json @@ -8,12 +8,11 @@ "sb_00", "user", "backup_folder_name", - "authorize_google_drive_access", - "last_backup_on", - "column_break_5", "backup_folder_id", - "enable_system_backup", + "authorize_google_drive_access", + "column_break_5", "frequency", + "last_backup_on", "refresh_token", "authorization_code" ], @@ -58,16 +57,10 @@ { "fieldname": "backup_folder_id", "fieldtype": "Data", - "label": "Backup Folder ID" + "label": "Backup Folder ID", + "read_only": 1 }, { - "default": "0", - "fieldname": "enable_system_backup", - "fieldtype": "Check", - "label": "Enable System Backup" - }, - { - "depends_on": "enable_system_backup", "fieldname": "frequency", "fieldtype": "Select", "label": "Frequency", @@ -93,7 +86,7 @@ } ], "issingle": 1, - "modified": "2019-08-13 17:36:13.014410", + "modified": "2019-08-15 22:13:14.637569", "modified_by": "Administrator", "module": "Integrations", "name": "Google Drive", diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index 8e62462b52..a5c6b53f3f 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -23,12 +23,6 @@ SCOPES = "https://www.googleapis.com/auth/drive/v3" class GoogleDrive(Document): - def validate(self): - if self.enable_system_backup: - system_backup = frappe.db.exists("Google Drive", {"enable_system_backup": 1}) - if system_backup and not system_backup == self.name: - frappe.throw(_("Google Drive System Backup can be enabled only for one account.")) - def get_access_token(self): google_settings = frappe.get_doc("Google Settings") @@ -179,7 +173,7 @@ def upload_system_backup_to_google_drive(): "parents": [account.backup_folder_id] } - media = MediaFileUpload(get_absolute_path(fileurl, True), mimetype="application/gzip", resumable=True) + media = MediaFileUpload(get_absolute_path(fileurl), mimetype="application/gzip", resumable=True) try: google_drive.files().create(body=file_metadata, media_body=media, fields="id").execute() @@ -190,19 +184,13 @@ def upload_system_backup_to_google_drive(): return _("Google Drive Backup Successful.") def daily_backup(): - g_drive = frappe.db.exists("Google Drive", {"enable": 1, "enable_system_backup": 1, "frequency": "Daily"}) - if g_drive: + if frappe.db.get_single_value("Google Drive", "frequency") == "Daily": upload_system_backup_to_google_drive() def weekly_backup(): - g_drive = frappe.db.exists("Google Drive", {"enable": 1, "enable_system_backup": 1, "frequency": "Weekly"}) - if g_drive: + if frappe.db.get_single_value("Google Drive", "frequency") == "Weekly": upload_system_backup_to_google_drive() -def get_absolute_path(filename, backup=False): - file_path = os.path.join(get_files_path()[2:], filename) - - if backup: - file_path = os.path.join(get_backups_path()[2:], filename) - +def get_absolute_path(filename): + file_path = os.path.join(get_backups_path()[2:], filename) return "{0}/sites/{1}".format(get_bench_path(), file_path) \ No newline at end of file From 344ce94c374aa6c6d30dfcfed35323d444a56f68 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 16 Aug 2019 10:49:58 +0530 Subject: [PATCH 23/58] fix: better progress status --- .../doctype/google_drive/google_drive.js | 12 +++++++++++- .../doctype/google_drive/google_drive.json | 8 ++++---- .../doctype/google_drive/google_drive.py | 14 ++++++++------ 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.js b/frappe/integrations/doctype/google_drive/google_drive.js index 2185f9bb69..e642866bdb 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.js +++ b/frappe/integrations/doctype/google_drive/google_drive.js @@ -7,7 +7,17 @@ frappe.ui.form.on('Google Drive', { frm.dashboard.set_headline(__("To use Google Drive, enable Google Settings.")); } - if (frm.doc.enable_system_backup) { + frappe.realtime.on("upload_to_google_drive", (data) => { + if (data.progress) { + frm.dashboard.show_progress("Uploading to Google Drive", data.progress / data.total * 100, + __("{0}", [data.message])); + if (data.progress === data.total) { + frm.dashboard.hide_progress("Uploading to Google Drive"); + } + } + }); + + if (frm.doc.refresh_token) { let sync_button = frm.add_custom_button(__("Take Backup"), function () { frappe.show_alert({ indicator: "green", diff --git a/frappe/integrations/doctype/google_drive/google_drive.json b/frappe/integrations/doctype/google_drive/google_drive.json index 2da4e6669d..34d968d50f 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.json +++ b/frappe/integrations/doctype/google_drive/google_drive.json @@ -1,5 +1,4 @@ { - "autoname": "field:backup_folder_name", "creation": "2019-08-13 17:24:05.470876", "doctype": "DocType", "engine": "InnoDB", @@ -8,10 +7,10 @@ "sb_00", "user", "backup_folder_name", - "backup_folder_id", + "frequency", "authorize_google_drive_access", "column_break_5", - "frequency", + "backup_folder_id", "last_backup_on", "refresh_token", "authorization_code" @@ -42,6 +41,7 @@ "fieldtype": "Data", "in_list_view": 1, "label": "Backup Folder Name", + "reqd": 1, "set_only_once": 1 }, { @@ -86,7 +86,7 @@ } ], "issingle": 1, - "modified": "2019-08-15 22:13:14.637569", + "modified": "2019-08-16 10:47:24.799056", "modified_by": "Administrator", "module": "Integrations", "name": "Google Drive", diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index a5c6b53f3f..4d9975fd87 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -107,9 +107,6 @@ def get_google_drive_object(): google_settings = frappe.get_doc("Google Settings") account = frappe.get_doc("Google Drive") - if not account.backup_folder_id: - frappe.throw(_("Folder {0} not created in Google Drive.").format(account.backup_folder_name)) - credentials_dict = { "token": account.get_access_token(), "refresh_token": account.get_password(fieldname="refresh_token", raise_exception=False), @@ -163,21 +160,23 @@ def upload_system_backup_to_google_drive(): # Check if folder exists in Google Drive check_for_folder_in_google_drive(google_drive, account) account.load_from_db() - + progress(1, "Backing up Data.") backup = new_backup(ignore_files=True) fileurl = os.path.basename(backup.backup_path_db) file_metadata = { - "name": "Instance Backup-{0}".format(frappe.utils.now()), + "name": fileurl, "parents": [account.backup_folder_id] } media = MediaFileUpload(get_absolute_path(fileurl), mimetype="application/gzip", resumable=True) try: + progress(2, "Uploading backup to Google Drive.") google_drive.files().create(body=file_metadata, media_body=media, fields="id").execute() frappe.db.set_value("Google Drive", None, "last_backup_on", frappe.utils.now_datetime()) + progress(3, "Uploading successful.") except HttpError as e: frappe.msgprint(_("Google Drive - Could not upload backup - Error {0}").format(e)) @@ -193,4 +192,7 @@ def weekly_backup(): def get_absolute_path(filename): file_path = os.path.join(get_backups_path()[2:], filename) - return "{0}/sites/{1}".format(get_bench_path(), file_path) \ No newline at end of file + return "{0}/sites/{1}".format(get_bench_path(), file_path) + +def progress(progress, message): + frappe.publish_realtime("upload_to_google_drive", dict(progress=progress, total=3, message=message), user=frappe.session.user) \ No newline at end of file From ba00fb749b3b9cc7f08c8cdf69a54768f35098b8 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 16 Aug 2019 10:53:32 +0530 Subject: [PATCH 24/58] chore: code cleanup --- frappe/integrations/doctype/google_drive/google_drive.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.json b/frappe/integrations/doctype/google_drive/google_drive.json index 34d968d50f..04ea90e96b 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.json +++ b/frappe/integrations/doctype/google_drive/google_drive.json @@ -64,7 +64,7 @@ "fieldname": "frequency", "fieldtype": "Select", "label": "Frequency", - "options": "Daily\nWeekly" + "options": "\nDaily\nWeekly" }, { "fieldname": "refresh_token", @@ -86,7 +86,7 @@ } ], "issingle": 1, - "modified": "2019-08-16 10:47:24.799056", + "modified": "2019-08-16 10:53:10.165267", "modified_by": "Administrator", "module": "Integrations", "name": "Google Drive", From a708dd932622f8a30838f65efc0d9096dafcbd78 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 16 Aug 2019 11:10:28 +0530 Subject: [PATCH 25/58] chore: remove unused imports --- frappe/integrations/doctype/google_drive/google_drive.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index 4d9975fd87..e3a2d2a13f 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -15,7 +15,7 @@ from frappe.model.document import Document from frappe.utils import get_request_site_address from six.moves.urllib.parse import quote from apiclient.http import MediaFileUpload -from frappe.utils import get_backups_path, get_files_path, get_bench_path +from frappe.utils import get_backups_path, get_bench_path from frappe.utils.backups import new_backup from frappe.integrations.doctype.google_settings.google_settings import get_auth_url From ac5fdff6011054d04638b4c424ad5e630ec20c91 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 16 Aug 2019 11:44:06 +0530 Subject: [PATCH 26/58] patch: delete gsuite template and settings --- frappe/patches/v12_0/delete_gsuite_if_exists.py | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 frappe/patches/v12_0/delete_gsuite_if_exists.py diff --git a/frappe/patches/v12_0/delete_gsuite_if_exists.py b/frappe/patches/v12_0/delete_gsuite_if_exists.py new file mode 100644 index 0000000000..7379ac9cdf --- /dev/null +++ b/frappe/patches/v12_0/delete_gsuite_if_exists.py @@ -0,0 +1,8 @@ +import frappe + +def execute(): + ''' + Remove GSuite Template and GSuite Settings + ''' + frappe.delete_doc_if_exists("DocType", "GSuite Settings") + frappe.delete_doc_if_exists("DocType", "GSuite Templates") \ No newline at end of file From c9fb2d5a5172f062db20053564976481bd1c0b4d Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 16 Aug 2019 16:53:47 +0530 Subject: [PATCH 27/58] feat: upload files to google_drive --- frappe/core/doctype/file/file.json | 952 ++++-------------- .../doctype/google_drive/google_drive.json | 35 +- .../doctype/google_drive/google_drive.py | 68 +- 3 files changed, 281 insertions(+), 774 deletions(-) diff --git a/frappe/core/doctype/file/file.json b/frappe/core/doctype/file/file.json index 81606ad0f6..9bf7d03512 100644 --- a/frappe/core/doctype/file/file.json +++ b/frappe/core/doctype/file/file.json @@ -1,792 +1,226 @@ { - "allow_copy": 0, - "allow_guest_to_view": 0, - "allow_import": 1, - "allow_rename": 0, - "autoname": "", - "beta": 0, - "creation": "2012-12-12 11:19:22", - "custom": 0, - "docstatus": 0, - "doctype": "DocType", - "editable_grid": 0, + "allow_import": 1, + "creation": "2012-12-12 11:19:22", + "doctype": "DocType", + "engine": "InnoDB", + "field_order": [ + "file_name", + "is_private", + "preview", + "preview_html", + "section_break_5", + "is_home_folder", + "is_attachments_folder", + "file_size", + "column_break_5", + "file_url", + "thumbnail_url", + "folder", + "is_folder", + "section_break_8", + "attached_to_doctype", + "column_break_10", + "attached_to_name", + "attached_to_field", + "lft", + "rgt", + "old_parent", + "content_hash", + "uploaded_to_dropbox", + "uploaded_to_google_drive" + ], "fields": [ { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "file_name", - "fieldtype": "Data", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 1, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "File Name", - "length": 0, - "no_copy": 0, - "oldfieldname": "file_name", - "oldfieldtype": "Data", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "file_name", + "fieldtype": "Data", + "in_global_search": 1, + "label": "File Name", + "oldfieldname": "file_name", + "oldfieldtype": "Data", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:!doc.is_folder", - "fieldname": "is_private", - "fieldtype": "Check", - "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": "Is Private", - "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, - "translatable": 0, - "unique": 0 - }, + "default": "0", + "depends_on": "eval:!doc.is_folder", + "fieldname": "is_private", + "fieldtype": "Check", + "label": "Is Private" + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "preview", - "fieldtype": "Section Break", - "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": "Preview", - "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, - "translatable": 0, - "unique": 0 - }, + "fieldname": "preview", + "fieldtype": "Section Break", + "label": "Preview" + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "preview_html", - "fieldtype": "HTML", - "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": "Preview HTML", - "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, - "translatable": 0, - "unique": 0 - }, + "fieldname": "preview_html", + "fieldtype": "HTML", + "label": "Preview HTML" + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "section_break_5", - "fieldtype": "Section Break", - "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, - "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, - "translatable": 0, - "unique": 0 - }, + "fieldname": "section_break_5", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "", - "fieldname": "is_home_folder", - "fieldtype": "Check", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Is Home Folder", - "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, - "translatable": 0, - "unique": 0 - }, + "default": "0", + "fieldname": "is_home_folder", + "fieldtype": "Check", + "hidden": 1, + "label": "Is Home Folder" + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "is_attachments_folder", - "fieldtype": "Check", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Is Attachments Folder", - "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, - "translatable": 0, - "unique": 0 - }, + "default": "0", + "fieldname": "is_attachments_folder", + "fieldtype": "Check", + "hidden": 1, + "label": "Is Attachments Folder" + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "file_size", - "fieldtype": "Int", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 1, - "in_standard_filter": 0, - "label": "File Size", - "length": 20, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "file_size", + "fieldtype": "Int", + "in_list_view": 1, + "label": "File Size", + "length": 20, + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_5", - "fieldtype": "Column Break", - "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, - "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, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_5", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:!doc.is_folder", - "fieldname": "file_url", - "fieldtype": "Code", - "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": "File URL", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "depends_on": "eval:!doc.is_folder", + "fieldname": "file_url", + "fieldtype": "Code", + "label": "File URL", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "thumbnail_url", - "fieldtype": "Small Text", - "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": "Thumbnail URL", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "thumbnail_url", + "fieldtype": "Small Text", + "label": "Thumbnail URL", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "folder", - "fieldtype": "Link", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "Folder", - "length": 0, - "no_copy": 0, - "options": "File", - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "folder", + "fieldtype": "Link", + "hidden": 1, + "label": "Folder", + "options": "File", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "is_folder", - "fieldtype": "Check", - "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": "Is Folder", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "default": "0", + "fieldname": "is_folder", + "fieldtype": "Check", + "label": "Is Folder", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "depends_on": "eval:!doc.is_folder", - "fieldname": "section_break_8", - "fieldtype": "Section Break", - "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, - "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, - "translatable": 0, - "unique": 0 - }, + "depends_on": "eval:!doc.is_folder", + "fieldname": "section_break_8", + "fieldtype": "Section Break" + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "attached_to_doctype", - "fieldtype": "Link", - "hidden": 0, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 1, - "label": "Attached To DocType", - "length": 0, - "no_copy": 0, - "options": "DocType", - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "attached_to_doctype", + "fieldtype": "Link", + "in_standard_filter": 1, + "label": "Attached To DocType", + "options": "DocType", + "read_only": 1, + "search_index": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "column_break_10", - "fieldtype": "Column Break", - "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, - "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, - "translatable": 0, - "unique": 0 - }, + "fieldname": "column_break_10", + "fieldtype": "Column Break" + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "attached_to_name", - "fieldtype": "Data", - "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": "Attached To Name", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 1, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "attached_to_name", + "fieldtype": "Data", + "label": "Attached To Name", + "read_only": 1, + "search_index": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "attached_to_field", - "fieldtype": "Data", - "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": "Attached To Field", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "attached_to_field", + "fieldtype": "Data", + "label": "Attached To Field", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "lft", - "fieldtype": "Int", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "lft", - "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, - "translatable": 0, - "unique": 0 - }, + "fieldname": "lft", + "fieldtype": "Int", + "hidden": 1, + "label": "lft" + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "rgt", - "fieldtype": "Int", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "rgt", - "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, - "translatable": 0, - "unique": 0 - }, + "fieldname": "rgt", + "fieldtype": "Int", + "hidden": 1, + "label": "rgt" + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "old_parent", - "fieldtype": "Data", - "hidden": 1, - "ignore_user_permissions": 0, - "ignore_xss_filter": 0, - "in_filter": 0, - "in_global_search": 0, - "in_list_view": 0, - "in_standard_filter": 0, - "label": "old_parent", - "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, - "translatable": 0, - "unique": 0 - }, + "fieldname": "old_parent", + "fieldtype": "Data", + "hidden": 1, + "label": "old_parent" + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "content_hash", - "fieldtype": "Data", - "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": "Content Hash", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 - }, + "fieldname": "content_hash", + "fieldtype": "Data", + "label": "Content Hash", + "read_only": 1 + }, { - "allow_bulk_edit": 0, - "allow_on_submit": 0, - "bold": 0, - "collapsible": 0, - "columns": 0, - "fieldname": "uploaded_to_dropbox", - "fieldtype": "Check", - "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": "Uploaded To Dropbox", - "length": 0, - "no_copy": 0, - "permlevel": 0, - "precision": "", - "print_hide": 0, - "print_hide_if_no_value": 0, - "read_only": 1, - "remember_last_selected_value": 0, - "report_hide": 0, - "reqd": 0, - "search_index": 0, - "set_only_once": 0, - "translatable": 0, - "unique": 0 + "default": "0", + "fieldname": "uploaded_to_dropbox", + "fieldtype": "Check", + "label": "Uploaded To Dropbox", + "read_only": 1 + }, + { + "default": "0", + "fieldname": "uploaded_to_google_drive", + "fieldtype": "Check", + "label": "Uploaded To Google Drive", + "read_only": 1 } - ], - "has_web_view": 0, - "hide_heading": 0, - "hide_toolbar": 0, - "icon": "fa fa-file", - "idx": 1, - "image_view": 0, - "in_create": 0, - "is_submittable": 0, - "issingle": 0, - "istable": 0, - "max_attachments": 0, - "menu_index": 0, - "modified": "2018-10-01 05:22:50.819899", - "modified_by": "Administrator", - "module": "Core", - "name": "File", - "owner": "Administrator", + ], + "icon": "fa fa-file", + "idx": 1, + "modified": "2019-08-16 16:41:03.086023", + "modified_by": "Administrator", + "module": "Core", + "name": "File", + "owner": "Administrator", "permissions": [ { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 0, - "import": 1, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "System Manager", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "import": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, "write": 1 - }, + }, { - "amend": 0, - "cancel": 0, - "create": 1, - "delete": 1, - "email": 1, - "export": 1, - "if_owner": 1, - "import": 0, - "permlevel": 0, - "print": 1, - "read": 1, - "report": 1, - "role": "All", - "set_user_permissions": 0, - "share": 1, - "submit": 0, + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "if_owner": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "All", + "share": 1, "write": 1 } - ], - "quick_entry": 0, - "read_only": 0, - "read_only_onload": 0, - "show_name_in_global_search": 0, - "sort_order": "ASC", - "title_field": "file_name", - "track_changes": 1, - "track_seen": 0 + ], + "sort_field": "modified", + "sort_order": "ASC", + "title_field": "file_name", + "track_changes": 1 } \ No newline at end of file diff --git a/frappe/integrations/doctype/google_drive/google_drive.json b/frappe/integrations/doctype/google_drive/google_drive.json index 04ea90e96b..f605831f32 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.json +++ b/frappe/integrations/doctype/google_drive/google_drive.json @@ -5,7 +5,9 @@ "field_order": [ "enable", "sb_00", - "user", + "email", + "send_email_for_successful_backup", + "file_backup", "backup_folder_name", "frequency", "authorize_google_drive_access", @@ -28,14 +30,6 @@ "fieldtype": "Section Break", "label": "Google Drive" }, - { - "fieldname": "user", - "fieldtype": "Link", - "in_list_view": 1, - "label": "User", - "options": "User", - "reqd": 1 - }, { "fieldname": "backup_folder_name", "fieldtype": "Data", @@ -83,10 +77,31 @@ "fieldtype": "Datetime", "label": "Last Backup On", "read_only": 1 + }, + { + "fieldname": "email", + "fieldtype": "Data", + "in_list_view": 1, + "label": "Email", + "options": "Email", + "reqd": 1 + }, + { + "default": "0", + "description": "Note: By default emails for failed backups are sent.", + "fieldname": "send_email_for_successful_backup", + "fieldtype": "Check", + "label": "Send Email for Successful backup" + }, + { + "default": "0", + "fieldname": "file_backup", + "fieldtype": "Check", + "label": "File Backup" } ], "issingle": 1, - "modified": "2019-08-16 10:53:10.165267", + "modified": "2019-08-16 16:23:36.686391", "modified_by": "Administrator", "module": "Integrations", "name": "Google Drive", diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index e3a2d2a13f..05f1a8c303 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -15,7 +15,7 @@ from frappe.model.document import Document from frappe.utils import get_request_site_address from six.moves.urllib.parse import quote from apiclient.http import MediaFileUpload -from frappe.utils import get_backups_path, get_bench_path +from frappe.utils import get_backups_path, get_files_path, get_bench_path from frappe.utils.backups import new_backup from frappe.integrations.doctype.google_settings.google_settings import get_auth_url @@ -170,18 +170,48 @@ def upload_system_backup_to_google_drive(): "parents": [account.backup_folder_id] } - media = MediaFileUpload(get_absolute_path(fileurl), mimetype="application/gzip", resumable=True) + media = MediaFileUpload(get_absolute_path(fileurl, True), mimetype="application/gzip", resumable=True) try: progress(2, "Uploading backup to Google Drive.") google_drive.files().create(body=file_metadata, media_body=media, fields="id").execute() + if account.file_backup: + progress(2, "Uploading files to Google Drive.") + upload_files(google_drive, account) + frappe.db.set_value("Google Drive", None, "last_backup_on", frappe.utils.now_datetime()) progress(3, "Uploading successful.") + send_email(success=True) except HttpError as e: + send_email(success=False, error=e) frappe.msgprint(_("Google Drive - Could not upload backup - Error {0}").format(e)) return _("Google Drive Backup Successful.") +def upload_files(google_drive, account): + for f in frappe.get_list("File", filters={"is_folder": 0, "uploaded_to_google_drive": 0}, + fields=["name", "file_url", "file_name", "is_private"]): + + upload_file_to_google_drive(google_drive, account, f.file_name or f.file_url, f.is_private) + frappe.db.set_value("File", f.name, "uploaded_to_google_drive", 1) + +def upload_file_to_google_drive(google_drive, account, fileurl, is_private): + """ + Uploads File to Folder specified in Google Drive Doc. + """ + # parents: Folder id under which the file is to be uploaded + file_metadata = { + "name": filename, + "parents": [account.backup_folder_id] + } + + media = MediaFileUpload(get_absolute_path(fileurl, is_private), mimetype="application/pdf", resumable=True) + + try: + google_drive.files().create(body=file_metadata, media_body=media, fields="id").execute() + except HttpError as e: + frappe.msgprint(_("Google Drive - Could not upload file - Error Code {0}").format(e)) + def daily_backup(): if frappe.db.get_single_value("Google Drive", "frequency") == "Daily": upload_system_backup_to_google_drive() @@ -190,9 +220,37 @@ def weekly_backup(): if frappe.db.get_single_value("Google Drive", "frequency") == "Weekly": upload_system_backup_to_google_drive() -def get_absolute_path(filename): - file_path = os.path.join(get_backups_path()[2:], filename) +def get_absolute_path(filename, is_private=False): + file_path = os.path.join(get_files_path()[2:], filename) + + if is_private: + file_path = os.path.join(get_backups_path()[2:], filename) return "{0}/sites/{1}".format(get_bench_path(), file_path) def progress(progress, message): - frappe.publish_realtime("upload_to_google_drive", dict(progress=progress, total=3, message=message), user=frappe.session.user) \ No newline at end of file + frappe.publish_realtime("upload_to_google_drive", dict(progress=progress, total=3, message=message), user=frappe.session.user) + +def send_email(success, error=None): + if success: + if not frappe.db.get_single_value("Google Drive", None, "send_email_for_successful_backup"): + return + + subject = "Backup Upload Successful" + message = """

Backup Uploaded Successfully

Hi there, this is just to inform you + that your backup was successfully uploaded to Google Drive.

+ """ + else: + subject = "[Warning] Backup Upload Failed" + message = """

Backup Upload Failed

Oops, your automated backup to Google Drive + failed.

+

Error message:
+

%s
+

+

Please contact your system manager for more information.

+ """.format(error) + + frappe.sendmail( + recipients=frappe.db.get_single_value("Google Drive", "email"), + subject=subject, + message=message + ) \ No newline at end of file From f7b729f35ff03c991be50319302efe4b6bd3d7c2 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 16 Aug 2019 16:57:23 +0530 Subject: [PATCH 28/58] fix: show folder_name --- frappe/integrations/doctype/google_drive/google_drive.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.json b/frappe/integrations/doctype/google_drive/google_drive.json index f605831f32..ff9f5578ad 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.json +++ b/frappe/integrations/doctype/google_drive/google_drive.json @@ -35,8 +35,7 @@ "fieldtype": "Data", "in_list_view": 1, "label": "Backup Folder Name", - "reqd": 1, - "set_only_once": 1 + "reqd": 1 }, { "depends_on": "eval:!doc.__islocal", @@ -101,7 +100,7 @@ } ], "issingle": 1, - "modified": "2019-08-16 16:23:36.686391", + "modified": "2019-08-16 16:57:11.475982", "modified_by": "Administrator", "module": "Integrations", "name": "Google Drive", From 6d2a072b9ac61dd13033ddf6cef5c4593d06bccb Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 16 Aug 2019 17:03:03 +0530 Subject: [PATCH 29/58] fix: scopes --- frappe/integrations/doctype/google_drive/google_drive.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index 05f1a8c303..d5b92b094a 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -19,7 +19,7 @@ from frappe.utils import get_backups_path, get_files_path, get_bench_path from frappe.utils.backups import new_backup from frappe.integrations.doctype.google_settings.google_settings import get_auth_url -SCOPES = "https://www.googleapis.com/auth/drive/v3" +SCOPES = "https://www.googleapis.com/auth/drive" class GoogleDrive(Document): @@ -113,7 +113,7 @@ def get_google_drive_object(): "token_uri": get_auth_url(), "client_id": google_settings.client_id, "client_secret": google_settings.get_password(fieldname="client_secret", raise_exception=False), - "scopes": SCOPES + "scopes": "https://www.googleapis.com/auth/drive/v3" } credentials = google.oauth2.credentials.Credentials(**credentials_dict) From a709d9bcb120ad4c0ca4fb1b9ad6695b0a67d6bd Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 16 Aug 2019 17:07:45 +0530 Subject: [PATCH 30/58] fix: redirect --- frappe/integrations/doctype/google_drive/google_drive.js | 1 - frappe/integrations/doctype/google_drive/google_drive.py | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.js b/frappe/integrations/doctype/google_drive/google_drive.js index e642866bdb..6f9a83c715 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.js +++ b/frappe/integrations/doctype/google_drive/google_drive.js @@ -41,7 +41,6 @@ frappe.ui.form.on('Google Drive', { frappe.call({ method: "frappe.integrations.doctype.google_drive.google_drive.authorize_access", args: { - "g_drive": frm.doc.name, "reauthorize": reauthorize }, callback: function(r) { diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index d5b92b094a..551ef0f53a 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -50,7 +50,7 @@ class GoogleDrive(Document): return r.get("access_token") @frappe.whitelist() -def authorize_access(g_drive, reauthorize=None): +def authorize_access(reauthorize=None): """ If no Authorization code get it from Google and then request for Refresh Token. Google Contact Name is set to flags to set_value after Authorization Code is obtained. @@ -98,7 +98,7 @@ def google_callback(code=None): frappe.db.set_value("Google Drive", None, "authorization_code", code) frappe.db.commit() - authorize_access(google_drive) + authorize_access() def get_google_drive_object(): """ From cee21f1a70beb3d4bf20b43520f7eefbbfa6928b Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 16 Aug 2019 17:14:21 +0530 Subject: [PATCH 31/58] fix: file name --- frappe/integrations/doctype/google_drive/google_drive.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index 551ef0f53a..f99d34434b 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -192,7 +192,7 @@ def upload_files(google_drive, account): for f in frappe.get_list("File", filters={"is_folder": 0, "uploaded_to_google_drive": 0}, fields=["name", "file_url", "file_name", "is_private"]): - upload_file_to_google_drive(google_drive, account, f.file_name or f.file_url, f.is_private) + upload_file_to_google_drive(google_drive, account, f.file_url or f.file_name, f.is_private) frappe.db.set_value("File", f.name, "uploaded_to_google_drive", 1) def upload_file_to_google_drive(google_drive, account, fileurl, is_private): @@ -200,12 +200,14 @@ def upload_file_to_google_drive(google_drive, account, fileurl, is_private): Uploads File to Folder specified in Google Drive Doc. """ # parents: Folder id under which the file is to be uploaded + filename = os.path.basename(fileurl) + file_metadata = { "name": filename, "parents": [account.backup_folder_id] } - media = MediaFileUpload(get_absolute_path(fileurl, is_private), mimetype="application/pdf", resumable=True) + media = MediaFileUpload(get_absolute_path(filename, is_private), mimetype="application/pdf", resumable=True) try: google_drive.files().create(body=file_metadata, media_body=media, fields="id").execute() From e2e76055d8b7539c26b95d7c6f27a9e9e4eb67a9 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 16 Aug 2019 20:25:01 +0530 Subject: [PATCH 32/58] fix: handle ioerror --- .../integrations/doctype/google_drive/google_drive.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index f99d34434b..1099244256 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -170,7 +170,10 @@ def upload_system_backup_to_google_drive(): "parents": [account.backup_folder_id] } - media = MediaFileUpload(get_absolute_path(fileurl, True), mimetype="application/gzip", resumable=True) + try: + media = MediaFileUpload(get_absolute_path(fileurl, True), mimetype="application/gzip", resumable=True) + except IOError as e: + frappe.throw(_("Google Drive - Could not locate locate - {0}").format(os.path.basename(e))) try: progress(2, "Uploading backup to Google Drive.") @@ -207,7 +210,10 @@ def upload_file_to_google_drive(google_drive, account, fileurl, is_private): "parents": [account.backup_folder_id] } - media = MediaFileUpload(get_absolute_path(filename, is_private), mimetype="application/pdf", resumable=True) + try: + media = MediaFileUpload(get_absolute_path(filename, is_private), mimetype="application/pdf", resumable=True) + except IOError as e: + frappe.msgprint(_("Google Drive - Could not locate file - {0}").format(os.path.basename(e))) try: google_drive.files().create(body=file_metadata, media_body=media, fields="id").execute() From babefc73802f86989a2d8d3ddf102ce3e7f187ff Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 16 Aug 2019 20:27:06 +0530 Subject: [PATCH 33/58] chore: code cleanup --- frappe/integrations/doctype/google_drive/google_drive.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index 1099244256..98959af25f 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -173,7 +173,7 @@ def upload_system_backup_to_google_drive(): try: media = MediaFileUpload(get_absolute_path(fileurl, True), mimetype="application/gzip", resumable=True) except IOError as e: - frappe.throw(_("Google Drive - Could not locate locate - {0}").format(os.path.basename(e))) + frappe.throw(_("Google Drive - Could not locate locate - {0}").format(e)) try: progress(2, "Uploading backup to Google Drive.") @@ -213,7 +213,7 @@ def upload_file_to_google_drive(google_drive, account, fileurl, is_private): try: media = MediaFileUpload(get_absolute_path(filename, is_private), mimetype="application/pdf", resumable=True) except IOError as e: - frappe.msgprint(_("Google Drive - Could not locate file - {0}").format(os.path.basename(e))) + frappe.msgprint(_("Google Drive - Could not locate file - {0}").format(e)) try: google_drive.files().create(body=file_metadata, media_body=media, fields="id").execute() From b4bb801f5940c086c3fcd7557308e31e559e0be2 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 16 Aug 2019 20:29:55 +0530 Subject: [PATCH 34/58] fix: return if file not found --- frappe/integrations/doctype/google_drive/google_drive.py | 1 + 1 file changed, 1 insertion(+) diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index 98959af25f..b5e808797b 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -214,6 +214,7 @@ def upload_file_to_google_drive(google_drive, account, fileurl, is_private): media = MediaFileUpload(get_absolute_path(filename, is_private), mimetype="application/pdf", resumable=True) except IOError as e: frappe.msgprint(_("Google Drive - Could not locate file - {0}").format(e)) + return try: google_drive.files().create(body=file_metadata, media_body=media, fields="id").execute() From 1480cb328586aad4369a2eaa303ffbbe0ac40fef Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Fri, 16 Aug 2019 20:36:16 +0530 Subject: [PATCH 35/58] fix: show dashboard if gdrive is disabled --- frappe/integrations/doctype/google_drive/google_drive.js | 2 +- frappe/integrations/doctype/google_drive/google_drive.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.js b/frappe/integrations/doctype/google_drive/google_drive.js index 6f9a83c715..1b1eeec631 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.js +++ b/frappe/integrations/doctype/google_drive/google_drive.js @@ -3,7 +3,7 @@ frappe.ui.form.on('Google Drive', { refresh: function(frm) { - if (frm.is_new()) { + if (!frm.doc.enable) { frm.dashboard.set_headline(__("To use Google Drive, enable Google Settings.")); } diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index b5e808797b..5627f22ca7 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -213,7 +213,7 @@ def upload_file_to_google_drive(google_drive, account, fileurl, is_private): try: media = MediaFileUpload(get_absolute_path(filename, is_private), mimetype="application/pdf", resumable=True) except IOError as e: - frappe.msgprint(_("Google Drive - Could not locate file - {0}").format(e)) + frappe.msgprint(_("Google Drive - File not found - {0}").format(e)) return try: From c7a40c7b392db2cb09dab3a737abd046382de889 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 19 Aug 2019 11:59:15 +0530 Subject: [PATCH 36/58] chore: codacy --- .../doctype/google_drive/google_drive.json | 16 ++++++++-------- .../doctype/google_drive/google_drive.py | 2 +- .../doctype/google_drive/test_google_drive.py | 10 ---------- 3 files changed, 9 insertions(+), 19 deletions(-) delete mode 100644 frappe/integrations/doctype/google_drive/test_google_drive.py diff --git a/frappe/integrations/doctype/google_drive/google_drive.json b/frappe/integrations/doctype/google_drive/google_drive.json index ff9f5578ad..5d5d23db81 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.json +++ b/frappe/integrations/doctype/google_drive/google_drive.json @@ -4,7 +4,7 @@ "engine": "InnoDB", "field_order": [ "enable", - "sb_00", + "google_drive_section", "email", "send_email_for_successful_backup", "file_backup", @@ -24,12 +24,6 @@ "fieldtype": "Check", "label": "Enable" }, - { - "depends_on": "enable", - "fieldname": "sb_00", - "fieldtype": "Section Break", - "label": "Google Drive" - }, { "fieldname": "backup_folder_name", "fieldtype": "Data", @@ -97,10 +91,16 @@ "fieldname": "file_backup", "fieldtype": "Check", "label": "File Backup" + }, + { + "depends_on": "enable", + "fieldname": "google_drive_section", + "fieldtype": "Section Break", + "label": "Google Drive" } ], "issingle": 1, - "modified": "2019-08-16 16:57:11.475982", + "modified": "2019-08-19 11:56:31.447432", "modified_by": "Administrator", "module": "Integrations", "name": "Google Drive", diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index 5627f22ca7..7eae941946 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -253,7 +253,7 @@ def send_email(success, error=None): message = """

Backup Upload Failed

Oops, your automated backup to Google Drive failed.

Error message:
-

%s
+
{0}

Please contact your system manager for more information.

""".format(error) diff --git a/frappe/integrations/doctype/google_drive/test_google_drive.py b/frappe/integrations/doctype/google_drive/test_google_drive.py deleted file mode 100644 index f06e13572c..0000000000 --- a/frappe/integrations/doctype/google_drive/test_google_drive.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt -from __future__ import unicode_literals - -# import frappe -import unittest - -class TestGoogleDrive(unittest.TestCase): - pass From f3bc7b0e30673406ec727e6c51ccf76bbe1178ba Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 19 Aug 2019 17:52:35 +0530 Subject: [PATCH 37/58] fix: single value --- frappe/integrations/doctype/google_drive/google_drive.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index 7eae941946..0297308bbc 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -241,7 +241,7 @@ def progress(progress, message): def send_email(success, error=None): if success: - if not frappe.db.get_single_value("Google Drive", None, "send_email_for_successful_backup"): + if not frappe.db.get_single_value("Google Drive", "send_email_for_successful_backup"): return subject = "Backup Upload Successful" From f56e0fa5abdb36201db31383a5b15b11941db588 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 19 Aug 2019 18:14:59 +0530 Subject: [PATCH 38/58] fix: folder creation --- .../doctype/google_drive/google_drive.js | 18 +++++++++++++++++- .../doctype/google_drive/google_drive.py | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.js b/frappe/integrations/doctype/google_drive/google_drive.js index 1b1eeec631..59f6d40ab6 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.js +++ b/frappe/integrations/doctype/google_drive/google_drive.js @@ -17,7 +17,23 @@ frappe.ui.form.on('Google Drive', { } }); - if (frm.doc.refresh_token) { + if (!frm.doc.backup_folder_id) { + let create_button = frm.add_custom_button(__("Create Folder"), function () { + frappe.show_alert({ + indicator: "green", + message: __("Creating folder in Google Drive.") + }); + frappe.call({ + method: "frappe.integrations.doctype.google_drive.google_drive.upload_system_backup_to_google_drive", + btn: create_button + }).then((r) => { + refresh_field(frm.doc.backup_folder_id); + frappe.msgprint(r.message); + }); + }); + } + + if (frm.doc.refresh_token && frm.doc.backup_folder_id) { let sync_button = frm.add_custom_button(__("Take Backup"), function () { frappe.show_alert({ indicator: "green", diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index 0297308bbc..b4121c5b22 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -121,6 +121,7 @@ def get_google_drive_object(): return google_drive, account +@frappe.whitelist() def create_folder_in_google_drive(google_drive, account): google_drive, account = get_google_drive_object() From 1b7880035186bc96209e9f530179697cf0c7b526 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 19 Aug 2019 18:34:32 +0530 Subject: [PATCH 39/58] fix: create folder --- frappe/integrations/doctype/google_drive/google_drive.js | 2 +- frappe/integrations/doctype/google_drive/google_drive.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.js b/frappe/integrations/doctype/google_drive/google_drive.js index 59f6d40ab6..93ed29cad8 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.js +++ b/frappe/integrations/doctype/google_drive/google_drive.js @@ -24,7 +24,7 @@ frappe.ui.form.on('Google Drive', { message: __("Creating folder in Google Drive.") }); frappe.call({ - method: "frappe.integrations.doctype.google_drive.google_drive.upload_system_backup_to_google_drive", + method: "frappe.integrations.doctype.google_drive.google_drive.create_folder_in_google_drive", btn: create_button }).then((r) => { refresh_field(frm.doc.backup_folder_id); diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index b4121c5b22..e322791cbe 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -122,7 +122,7 @@ def get_google_drive_object(): return google_drive, account @frappe.whitelist() -def create_folder_in_google_drive(google_drive, account): +def create_folder_in_google_drive(): google_drive, account = get_google_drive_object() file_metadata = { @@ -142,7 +142,7 @@ def check_for_folder_in_google_drive(google_drive, account): Create a folder on Drive, returns the newely created folders ID """ if not account.backup_folder_id: - create_folder_in_google_drive(google_drive, account) + create_folder_in_google_drive() return try: From 7a5b0a757520116cc4ab5c28aeef8c5279c60fe5 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 19 Aug 2019 18:55:45 +0530 Subject: [PATCH 40/58] fix: folder creation --- frappe/integrations/doctype/google_drive/google_drive.js | 5 ++--- frappe/integrations/doctype/google_drive/google_drive.py | 2 -- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.js b/frappe/integrations/doctype/google_drive/google_drive.js index 93ed29cad8..cde72f5759 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.js +++ b/frappe/integrations/doctype/google_drive/google_drive.js @@ -26,9 +26,8 @@ frappe.ui.form.on('Google Drive', { frappe.call({ method: "frappe.integrations.doctype.google_drive.google_drive.create_folder_in_google_drive", btn: create_button - }).then((r) => { - refresh_field(frm.doc.backup_folder_id); - frappe.msgprint(r.message); + }).then(() => { + frm.refresh(); }); }); } diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index e322791cbe..d3e5e802fe 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -135,8 +135,6 @@ def create_folder_in_google_drive(): except HttpError as e: frappe.throw(_("Google Drive - Could not create folder in Google Drive - Error Code {0}").format(e)) - return "Folder created successfully in Google Drive." - def check_for_folder_in_google_drive(google_drive, account): """ Create a folder on Drive, returns the newely created folders ID From 612a7336e83644500ea060fb9cd3d9a7a204b780 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Mon, 19 Aug 2019 19:29:43 +0530 Subject: [PATCH 41/58] fix: folder creation --- frappe/integrations/doctype/google_drive/google_drive.js | 5 +++-- frappe/integrations/doctype/google_drive/google_drive.py | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.js b/frappe/integrations/doctype/google_drive/google_drive.js index cde72f5759..a9335e9034 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.js +++ b/frappe/integrations/doctype/google_drive/google_drive.js @@ -26,8 +26,9 @@ frappe.ui.form.on('Google Drive', { frappe.call({ method: "frappe.integrations.doctype.google_drive.google_drive.create_folder_in_google_drive", btn: create_button - }).then(() => { - frm.refresh(); + }).then((r) => { + frappe.msgprint(r.message); + frm.refresh_field("backup_folder_id"); }); }); } diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index d3e5e802fe..609b77d32a 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -135,6 +135,8 @@ def create_folder_in_google_drive(): except HttpError as e: frappe.throw(_("Google Drive - Could not create folder in Google Drive - Error Code {0}").format(e)) + return _("Folder Created in Google Drive.") + def check_for_folder_in_google_drive(google_drive, account): """ Create a folder on Drive, returns the newely created folders ID From 3f6ced434fa05db6b766ec2f0998515b6abbb1ce Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Tue, 20 Aug 2019 19:49:39 +0530 Subject: [PATCH 42/58] fix: private files path --- .../integrations/doctype/google_drive/google_drive.js | 10 +++++++++- .../doctype/google_drive/google_drive.json | 11 ++++++----- .../integrations/doctype/google_drive/google_drive.py | 8 ++++---- .../doctype/google_drive/test_google_drive.py | 10 ++++++++++ 4 files changed, 29 insertions(+), 10 deletions(-) create mode 100644 frappe/integrations/doctype/google_drive/test_google_drive.py diff --git a/frappe/integrations/doctype/google_drive/google_drive.js b/frappe/integrations/doctype/google_drive/google_drive.js index a9335e9034..b9294bed81 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.js +++ b/frappe/integrations/doctype/google_drive/google_drive.js @@ -17,7 +17,7 @@ frappe.ui.form.on('Google Drive', { } }); - if (!frm.doc.backup_folder_id) { + if (frm.doc.refresh_token && !frm.doc.backup_folder_id) { let create_button = frm.add_custom_button(__("Create Folder"), function () { frappe.show_alert({ indicator: "green", @@ -47,6 +47,14 @@ frappe.ui.form.on('Google Drive', { }); }); } + + if (frm.doc.enable && frm.doc.backup_folder_name) { + frm.dashboard.set_headline(__("Enable Google Drive Access.")); + } + + if (frm.doc.refresh_token && frm.doc.authorization_code && frm.doc.enable) { + frm.page.set_indicator("Authorized", "green"); + } }, authorize_google_drive_access: function(frm) { let reauthorize = 0; diff --git a/frappe/integrations/doctype/google_drive/google_drive.json b/frappe/integrations/doctype/google_drive/google_drive.json index 5d5d23db81..819791ed0a 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.json +++ b/frappe/integrations/doctype/google_drive/google_drive.json @@ -6,10 +6,10 @@ "enable", "google_drive_section", "email", - "send_email_for_successful_backup", - "file_backup", "backup_folder_name", "frequency", + "send_email_for_successful_backup", + "file_backup", "authorize_google_drive_access", "column_break_5", "backup_folder_id", @@ -51,7 +51,8 @@ "fieldname": "frequency", "fieldtype": "Select", "label": "Frequency", - "options": "\nDaily\nWeekly" + "options": "\nDaily\nWeekly", + "reqd": 1 }, { "fieldname": "refresh_token", @@ -100,8 +101,8 @@ } ], "issingle": 1, - "modified": "2019-08-19 11:56:31.447432", - "modified_by": "Administrator", + "modified": "2019-08-20 14:25:24.504705", + "modified_by": "qwe@qwe.com", "module": "Integrations", "name": "Google Drive", "owner": "Administrator", diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index 609b77d32a..1e40d30b94 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -172,7 +172,7 @@ def upload_system_backup_to_google_drive(): } try: - media = MediaFileUpload(get_absolute_path(fileurl, True), mimetype="application/gzip", resumable=True) + media = MediaFileUpload(get_absolute_path(filename=fileurl, backup=True), mimetype="application/gzip", resumable=True) except IOError as e: frappe.throw(_("Google Drive - Could not locate locate - {0}").format(e)) @@ -212,7 +212,7 @@ def upload_file_to_google_drive(google_drive, account, fileurl, is_private): } try: - media = MediaFileUpload(get_absolute_path(filename, is_private), mimetype="application/pdf", resumable=True) + media = MediaFileUpload(get_absolute_path(filename=filename, is_private=is_private), mimetype="application/pdf", resumable=True) except IOError as e: frappe.msgprint(_("Google Drive - File not found - {0}").format(e)) return @@ -230,8 +230,8 @@ def weekly_backup(): if frappe.db.get_single_value("Google Drive", "frequency") == "Weekly": upload_system_backup_to_google_drive() -def get_absolute_path(filename, is_private=False): - file_path = os.path.join(get_files_path()[2:], filename) +def get_absolute_path(filename, is_private=False, backup=False): + file_path = os.path.join(get_files_path(is_private=is_private)[2:], filename) if is_private: file_path = os.path.join(get_backups_path()[2:], filename) diff --git a/frappe/integrations/doctype/google_drive/test_google_drive.py b/frappe/integrations/doctype/google_drive/test_google_drive.py new file mode 100644 index 0000000000..f06e13572c --- /dev/null +++ b/frappe/integrations/doctype/google_drive/test_google_drive.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019, Frappe Technologies and Contributors +# See license.txt +from __future__ import unicode_literals + +# import frappe +import unittest + +class TestGoogleDrive(unittest.TestCase): + pass From 34d729a468d913fd1934b847046898f7fd72293f Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Tue, 20 Aug 2019 19:54:03 +0530 Subject: [PATCH 43/58] fix: backup path --- frappe/integrations/doctype/google_drive/google_drive.js | 2 +- frappe/integrations/doctype/google_drive/google_drive.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.js b/frappe/integrations/doctype/google_drive/google_drive.js index b9294bed81..54ebe14c87 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.js +++ b/frappe/integrations/doctype/google_drive/google_drive.js @@ -48,7 +48,7 @@ frappe.ui.form.on('Google Drive', { }); } - if (frm.doc.enable && frm.doc.backup_folder_name) { + if (frm.doc.enable && frm.doc.backup_folder_name && !frm.doc.backup_folder_id) { frm.dashboard.set_headline(__("Enable Google Drive Access.")); } diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index 1e40d30b94..0d1462fabb 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -233,7 +233,7 @@ def weekly_backup(): def get_absolute_path(filename, is_private=False, backup=False): file_path = os.path.join(get_files_path(is_private=is_private)[2:], filename) - if is_private: + if backup: file_path = os.path.join(get_backups_path()[2:], filename) return "{0}/sites/{1}".format(get_bench_path(), file_path) From cab10700f432ae31dcd57e3a288de154edccda9b Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Tue, 20 Aug 2019 20:20:59 +0530 Subject: [PATCH 44/58] fix: show headline when no refresh token --- frappe/integrations/doctype/google_drive/google_drive.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.js b/frappe/integrations/doctype/google_drive/google_drive.js index 54ebe14c87..fc828ef0c6 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.js +++ b/frappe/integrations/doctype/google_drive/google_drive.js @@ -48,11 +48,11 @@ frappe.ui.form.on('Google Drive', { }); } - if (frm.doc.enable && frm.doc.backup_folder_name && !frm.doc.backup_folder_id) { + if (frm.doc.enable && frm.doc.backup_folder_name && !frm.doc.refresh_token) { frm.dashboard.set_headline(__("Enable Google Drive Access.")); } - if (frm.doc.refresh_token && frm.doc.authorization_code && frm.doc.enable) { + if (frm.doc.enable && frm.doc.refresh_token && frm.doc.authorization_code) { frm.page.set_indicator("Authorized", "green"); } }, From 6a9d995a2b39997abe206bc39be0a1b2901a26cd Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Tue, 20 Aug 2019 20:25:54 +0530 Subject: [PATCH 45/58] chore: remove test files --- .../doctype/google_calendar/test_google_calendar.py | 10 ---------- .../doctype/google_drive/test_google_drive.py | 10 ---------- 2 files changed, 20 deletions(-) delete mode 100644 frappe/integrations/doctype/google_calendar/test_google_calendar.py delete mode 100644 frappe/integrations/doctype/google_drive/test_google_drive.py diff --git a/frappe/integrations/doctype/google_calendar/test_google_calendar.py b/frappe/integrations/doctype/google_calendar/test_google_calendar.py deleted file mode 100644 index 0fad81d7f5..0000000000 --- a/frappe/integrations/doctype/google_calendar/test_google_calendar.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt -from __future__ import unicode_literals - -# import frappe -import unittest - -class TestGoogleCalendar(unittest.TestCase): - pass diff --git a/frappe/integrations/doctype/google_drive/test_google_drive.py b/frappe/integrations/doctype/google_drive/test_google_drive.py deleted file mode 100644 index f06e13572c..0000000000 --- a/frappe/integrations/doctype/google_drive/test_google_drive.py +++ /dev/null @@ -1,10 +0,0 @@ -# -*- coding: utf-8 -*- -# Copyright (c) 2019, Frappe Technologies and Contributors -# See license.txt -from __future__ import unicode_literals - -# import frappe -import unittest - -class TestGoogleDrive(unittest.TestCase): - pass From 917b4106323f2f54c13b89f0009f324b2d737c61 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 21 Aug 2019 11:06:00 +0530 Subject: [PATCH 46/58] fix: refresh form after creating folder --- frappe/integrations/doctype/google_drive/google_drive.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.js b/frappe/integrations/doctype/google_drive/google_drive.js index fc828ef0c6..e72a603d4a 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.js +++ b/frappe/integrations/doctype/google_drive/google_drive.js @@ -28,7 +28,7 @@ frappe.ui.form.on('Google Drive', { btn: create_button }).then((r) => { frappe.msgprint(r.message); - frm.refresh_field("backup_folder_id"); + frm.refresh(); }); }); } From bb1c1c150c1d64f6252d3e759660e4c5e7068685 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 21 Aug 2019 16:44:43 +0530 Subject: [PATCH 47/58] fix: reset auth refresh token when email change --- frappe/integrations/doctype/google_drive/google_drive.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index 0d1462fabb..a61e076b19 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -23,6 +23,12 @@ SCOPES = "https://www.googleapis.com/auth/drive" class GoogleDrive(Document): + def validate(self): + if not self.email == frappe.db.get_single_value("Google Drive", "email"): + self.authorization_code = "" + self.refresh_token = "" + self.backup_folder_id = "" + def get_access_token(self): google_settings = frappe.get_doc("Google Settings") From 951cb5459b8449e13ab873aa380a3d51d83c9a39 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 21 Aug 2019 16:54:17 +0530 Subject: [PATCH 48/58] fix: dashboard headline --- frappe/integrations/doctype/google_drive/google_drive.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.js b/frappe/integrations/doctype/google_drive/google_drive.js index e72a603d4a..2e4d83a880 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.js +++ b/frappe/integrations/doctype/google_drive/google_drive.js @@ -49,7 +49,7 @@ frappe.ui.form.on('Google Drive', { } if (frm.doc.enable && frm.doc.backup_folder_name && !frm.doc.refresh_token) { - frm.dashboard.set_headline(__("Enable Google Drive Access.")); + frm.dashboard.set_headline(__("Click on Authorize Google Drive Access to authorize Google Drive Access.")); } if (frm.doc.enable && frm.doc.refresh_token && frm.doc.authorization_code) { From 7aa975a98f5f4428d71760eed1fe7123cf332ca5 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 21 Aug 2019 17:23:09 +0530 Subject: [PATCH 49/58] fix: upload gz files --- frappe/config/integrations.py | 5 ++ .../doctype/google_drive/google_drive.json | 11 +-- .../doctype/google_drive/google_drive.py | 87 +++++-------------- .../doctype/google_drive/test_google_drive.py | 10 +++ 4 files changed, 40 insertions(+), 73 deletions(-) create mode 100644 frappe/integrations/doctype/google_drive/test_google_drive.py diff --git a/frappe/config/integrations.py b/frappe/config/integrations.py index bfed056546..f41adc9ea4 100644 --- a/frappe/config/integrations.py +++ b/frappe/config/integrations.py @@ -42,6 +42,11 @@ def get_data(): "name": "S3 Backup Settings", "description": _("S3 Backup Settings"), }, + { + "type": "doctype", + "name": "Google Drive", + "description": _("Google Drive Backup."), + } ] }, { diff --git a/frappe/integrations/doctype/google_drive/google_drive.json b/frappe/integrations/doctype/google_drive/google_drive.json index 819791ed0a..cc129ff77b 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.json +++ b/frappe/integrations/doctype/google_drive/google_drive.json @@ -5,7 +5,6 @@ "field_order": [ "enable", "google_drive_section", - "email", "backup_folder_name", "frequency", "send_email_for_successful_backup", @@ -72,14 +71,6 @@ "label": "Last Backup On", "read_only": 1 }, - { - "fieldname": "email", - "fieldtype": "Data", - "in_list_view": 1, - "label": "Email", - "options": "Email", - "reqd": 1 - }, { "default": "0", "description": "Note: By default emails for failed backups are sent.", @@ -101,7 +92,7 @@ } ], "issingle": 1, - "modified": "2019-08-20 14:25:24.504705", + "modified": "2019-08-21 17:07:21.773252", "modified_by": "qwe@qwe.com", "module": "Integrations", "name": "Google Drive", diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index a61e076b19..759facd518 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -23,12 +23,6 @@ SCOPES = "https://www.googleapis.com/auth/drive" class GoogleDrive(Document): - def validate(self): - if not self.email == frappe.db.get_single_value("Google Drive", "email"): - self.authorization_code = "" - self.refresh_token = "" - self.backup_folder_id = "" - def get_access_token(self): google_settings = frappe.get_doc("Google Settings") @@ -168,66 +162,36 @@ def upload_system_backup_to_google_drive(): check_for_folder_in_google_drive(google_drive, account) account.load_from_db() progress(1, "Backing up Data.") - backup = new_backup(ignore_files=True) + backup = new_backup() - fileurl = os.path.basename(backup.backup_path_db) + fileurl_backup = os.path.basename(backup.backup_path_db) + fileurl_public_files = os.path.basename(backup.backup_path_files) + fileurl_private_files = os.path.basename(backup.backup_path_private_files) - file_metadata = { - "name": fileurl, - "parents": [account.backup_folder_id] - } - try: - media = MediaFileUpload(get_absolute_path(filename=fileurl, backup=True), mimetype="application/gzip", resumable=True) - except IOError as e: - frappe.throw(_("Google Drive - Could not locate locate - {0}").format(e)) + for file_url in [fileurl_backup, fileurl_public_files, fileurl_private_files]: + file_metadata = { + "name": fileurl, + "parents": [account.backup_folder_id] + } - try: - progress(2, "Uploading backup to Google Drive.") - google_drive.files().create(body=file_metadata, media_body=media, fields="id").execute() - if account.file_backup: - progress(2, "Uploading files to Google Drive.") - upload_files(google_drive, account) + try: + media = MediaFileUpload(get_absolute_path(filename=fileurl), mimetype="application/gzip", resumable=True) + except IOError as e: + frappe.throw(_("Google Drive - Could not locate locate - {0}").format(e)) - frappe.db.set_value("Google Drive", None, "last_backup_on", frappe.utils.now_datetime()) - progress(3, "Uploading successful.") - send_email(success=True) - except HttpError as e: - send_email(success=False, error=e) - frappe.msgprint(_("Google Drive - Could not upload backup - Error {0}").format(e)) + try: + progress(2, "Uploading backup to Google Drive.") + google_drive.files().create(body=file_metadata, media_body=media, fields="id").execute() + except HttpError as e: + send_email(success=False, error=e) + frappe.msgprint(_("Google Drive - Could not upload backup - Error {0}").format(e)) + progress(3, "Uploading successful.") + frappe.db.set_value("Google Drive", None, "last_backup_on", frappe.utils.now_datetime()) + send_email(success=True) return _("Google Drive Backup Successful.") -def upload_files(google_drive, account): - for f in frappe.get_list("File", filters={"is_folder": 0, "uploaded_to_google_drive": 0}, - fields=["name", "file_url", "file_name", "is_private"]): - - upload_file_to_google_drive(google_drive, account, f.file_url or f.file_name, f.is_private) - frappe.db.set_value("File", f.name, "uploaded_to_google_drive", 1) - -def upload_file_to_google_drive(google_drive, account, fileurl, is_private): - """ - Uploads File to Folder specified in Google Drive Doc. - """ - # parents: Folder id under which the file is to be uploaded - filename = os.path.basename(fileurl) - - file_metadata = { - "name": filename, - "parents": [account.backup_folder_id] - } - - try: - media = MediaFileUpload(get_absolute_path(filename=filename, is_private=is_private), mimetype="application/pdf", resumable=True) - except IOError as e: - frappe.msgprint(_("Google Drive - File not found - {0}").format(e)) - return - - try: - google_drive.files().create(body=file_metadata, media_body=media, fields="id").execute() - except HttpError as e: - frappe.msgprint(_("Google Drive - Could not upload file - Error Code {0}").format(e)) - def daily_backup(): if frappe.db.get_single_value("Google Drive", "frequency") == "Daily": upload_system_backup_to_google_drive() @@ -236,11 +200,8 @@ def weekly_backup(): if frappe.db.get_single_value("Google Drive", "frequency") == "Weekly": upload_system_backup_to_google_drive() -def get_absolute_path(filename, is_private=False, backup=False): - file_path = os.path.join(get_files_path(is_private=is_private)[2:], filename) - - if backup: - file_path = os.path.join(get_backups_path()[2:], filename) +def get_absolute_path(filename): + file_path = os.path.join(get_backups_path()[2:], filename) return "{0}/sites/{1}".format(get_bench_path(), file_path) def progress(progress, message): diff --git a/frappe/integrations/doctype/google_drive/test_google_drive.py b/frappe/integrations/doctype/google_drive/test_google_drive.py new file mode 100644 index 0000000000..f06e13572c --- /dev/null +++ b/frappe/integrations/doctype/google_drive/test_google_drive.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019, Frappe Technologies and Contributors +# See license.txt +from __future__ import unicode_literals + +# import frappe +import unittest + +class TestGoogleDrive(unittest.TestCase): + pass From 9b70c01e872930a3abfd5c3dbc3accef6bad4501 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 21 Aug 2019 17:37:48 +0530 Subject: [PATCH 50/58] fix: queue google drive backup --- .../integrations/doctype/google_drive/google_drive.js | 4 ++-- .../doctype/google_drive/google_drive.json | 10 +++++++++- .../integrations/doctype/google_drive/google_drive.py | 7 ++++++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.js b/frappe/integrations/doctype/google_drive/google_drive.js index 2e4d83a880..034b18d2a8 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.js +++ b/frappe/integrations/doctype/google_drive/google_drive.js @@ -27,8 +27,8 @@ frappe.ui.form.on('Google Drive', { method: "frappe.integrations.doctype.google_drive.google_drive.create_folder_in_google_drive", btn: create_button }).then((r) => { - frappe.msgprint(r.message); frm.refresh(); + frappe.msgprint(r.message); }); }); } @@ -40,7 +40,7 @@ frappe.ui.form.on('Google Drive', { message: __("Backing up to Google Drive.") }); frappe.call({ - method: "frappe.integrations.doctype.google_drive.google_drive.upload_system_backup_to_google_drive", + method: "frappe.integrations.doctype.google_drive.google_drive.take_backup", btn: sync_button }).then((r) => { frappe.msgprint(r.message); diff --git a/frappe/integrations/doctype/google_drive/google_drive.json b/frappe/integrations/doctype/google_drive/google_drive.json index cc129ff77b..7ea26dadc8 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.json +++ b/frappe/integrations/doctype/google_drive/google_drive.json @@ -7,6 +7,7 @@ "google_drive_section", "backup_folder_name", "frequency", + "email", "send_email_for_successful_backup", "file_backup", "authorize_google_drive_access", @@ -89,10 +90,17 @@ "fieldname": "google_drive_section", "fieldtype": "Section Break", "label": "Google Drive" + }, + { + "fieldname": "email", + "fieldtype": "Data", + "label": "Send Notification To", + "options": "Email", + "reqd": 1 } ], "issingle": 1, - "modified": "2019-08-21 17:07:21.773252", + "modified": "2019-08-21 17:33:28.516614", "modified_by": "qwe@qwe.com", "module": "Integrations", "name": "Google Drive", diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index 759facd518..a3cd5602b5 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -151,6 +151,11 @@ def check_for_folder_in_google_drive(google_drive, account): frappe.throw(_("Google Drive - Could not find folder in Google Drive - Error Code {0}.").format(e)) @frappe.whitelist() +def take_backup(): + """Enqueue longjob for taking backup to Google Drive""" + enqueue("frappe.integrations.doctype.google_drive.google_drive.upload_system_backup_to_google_drive", queue='long', timeout=1500) + frappe.msgprint(_("Queued for backup. It may take a few minutes to an hour.")) + def upload_system_backup_to_google_drive(): """ Upload system backup to Google Drive @@ -169,7 +174,7 @@ def upload_system_backup_to_google_drive(): fileurl_private_files = os.path.basename(backup.backup_path_private_files) - for file_url in [fileurl_backup, fileurl_public_files, fileurl_private_files]: + for fileurl in [fileurl_backup, fileurl_public_files, fileurl_private_files]: file_metadata = { "name": fileurl, "parents": [account.backup_folder_id] From 1abf318b49e089b38c89e3fac296acb49e684ee5 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 21 Aug 2019 17:40:38 +0530 Subject: [PATCH 51/58] fix: import enqueue --- frappe/integrations/doctype/google_drive/google_drive.py | 1 + 1 file changed, 1 insertion(+) diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index a3cd5602b5..0da6f8cd1f 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -13,6 +13,7 @@ from frappe import _ from googleapiclient.errors import HttpError from frappe.model.document import Document from frappe.utils import get_request_site_address +from frappe.utils.background_jobs import enqueue from six.moves.urllib.parse import quote from apiclient.http import MediaFileUpload from frappe.utils import get_backups_path, get_files_path, get_bench_path From c33317ccf8b58565c3c97213d7f6a2652f58da3d Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 21 Aug 2019 17:45:54 +0530 Subject: [PATCH 52/58] fix: reset folder id on reauthorize --- frappe/integrations/doctype/google_drive/google_drive.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index 0da6f8cd1f..8a9caa7654 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -63,6 +63,8 @@ def authorize_access(reauthorize=None): redirect_uri = get_request_site_address(True) + "?cmd=frappe.integrations.doctype.google_drive.google_drive.google_callback" if not google_drive.authorization_code or reauthorize: + if reauthorize: + frappe.db.set_value("Google Drive", None, "backup_folder_id", "") return get_authentication_url(client_id=google_settings.client_id, redirect_uri=redirect_uri) else: try: From 38e2fad23aa4f1e5c1d4466ae67c38ccc649ceb3 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 21 Aug 2019 17:57:12 +0530 Subject: [PATCH 53/58] fix: do not show take backup if not enable --- frappe/integrations/doctype/google_drive/google_drive.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.js b/frappe/integrations/doctype/google_drive/google_drive.js index 034b18d2a8..bcdb3fbc77 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.js +++ b/frappe/integrations/doctype/google_drive/google_drive.js @@ -17,7 +17,7 @@ frappe.ui.form.on('Google Drive', { } }); - if (frm.doc.refresh_token && !frm.doc.backup_folder_id) { + if (frm.doc.enable && frm.doc.refresh_token && !frm.doc.backup_folder_id) { let create_button = frm.add_custom_button(__("Create Folder"), function () { frappe.show_alert({ indicator: "green", @@ -33,7 +33,7 @@ frappe.ui.form.on('Google Drive', { }); } - if (frm.doc.refresh_token && frm.doc.backup_folder_id) { + if (frm.doc.enable && frm.doc.refresh_token && frm.doc.backup_folder_id) { let sync_button = frm.add_custom_button(__("Take Backup"), function () { frappe.show_alert({ indicator: "green", From 8e578d3b0f0727727f7af1e0e4f56ee33456f3b7 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 21 Aug 2019 18:22:29 +0530 Subject: [PATCH 54/58] fix: find folder if already exists --- .../doctype/google_drive/google_drive.py | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index 8a9caa7654..f0220227a2 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -126,17 +126,35 @@ def get_google_drive_object(): @frappe.whitelist() def create_folder_in_google_drive(): - google_drive, account = get_google_drive_object() + def _create_folder_in_google_drive(google_drive, account): + file_metadata = { + "name": account.backup_folder_name, + "mimeType": "application/vnd.google-apps.folder" + } + + try: + folder = google_drive.files().create(body=file_metadata, fields="id").execute() + frappe.db.set_value("Google Drive", None, "backup_folder_id", folder.get("id")) + except HttpError as e: + frappe.throw(_("Google Drive - Could not create folder in Google Drive - Error Code {0}").format(e)) + + google_drive, account = get_google_drive_object() + backup_folder_exists = False - file_metadata = { - "name": account.backup_folder_name, - "mimeType": "application/vnd.google-apps.folder" - } try: - folder = google_drive.files().create(body=file_metadata, fields="id").execute() - frappe.db.set_value("Google Drive", None, "backup_folder_id", folder.get("id")) + folder_exists = google_drive.files().list(q="mimeType='application/vnd.google-apps.folder'".format(account.backup_folder_name)).execute().get("files", []) except HttpError as e: - frappe.throw(_("Google Drive - Could not create folder in Google Drive - Error Code {0}").format(e)) + frappe.throw(_("Google Drive - Could not find folder in Google Drive - Error Code {0}").format(e)) + + if folder_exists: + for f in folder_exists: + if f.get("name") == account.backup_folder_name: + frappe.db.set_value("Google Drive", None, "backup_folder_id", f.get("id")) + backup_folder_exists = True + break + + if not backup_folder_exists: + _create_folder_in_google_drive(google_drive, account) return _("Folder Created in Google Drive.") From b4084de9ab64dab4128f93c3e3f1442c9e33f553 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 21 Aug 2019 19:04:38 +0530 Subject: [PATCH 55/58] fix: create folder if not exists --- .../doctype/google_drive/google_drive.js | 18 +-------- .../doctype/google_drive/google_drive.py | 39 +++++++++---------- 2 files changed, 19 insertions(+), 38 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.js b/frappe/integrations/doctype/google_drive/google_drive.js index bcdb3fbc77..ec3323f89b 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.js +++ b/frappe/integrations/doctype/google_drive/google_drive.js @@ -17,23 +17,7 @@ frappe.ui.form.on('Google Drive', { } }); - if (frm.doc.enable && frm.doc.refresh_token && !frm.doc.backup_folder_id) { - let create_button = frm.add_custom_button(__("Create Folder"), function () { - frappe.show_alert({ - indicator: "green", - message: __("Creating folder in Google Drive.") - }); - frappe.call({ - method: "frappe.integrations.doctype.google_drive.google_drive.create_folder_in_google_drive", - btn: create_button - }).then((r) => { - frm.refresh(); - frappe.msgprint(r.message); - }); - }); - } - - if (frm.doc.enable && frm.doc.refresh_token && frm.doc.backup_folder_id) { + if (frm.doc.enable && frm.doc.refresh_token) { let sync_button = frm.add_custom_button(__("Take Backup"), function () { frappe.show_alert({ indicator: "green", diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index f0220227a2..c83165d87f 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -24,6 +24,11 @@ SCOPES = "https://www.googleapis.com/auth/drive" class GoogleDrive(Document): + def validate(self): + doc_before_save = self.get_doc_before_save() + if doc_before_save and doc_before_save.backup_folder_name != self.backup_folder_name: + self.backup_folder_id = '' + def get_access_token(self): google_settings = frappe.get_doc("Google Settings") @@ -124,8 +129,8 @@ def get_google_drive_object(): return google_drive, account -@frappe.whitelist() -def create_folder_in_google_drive(): +def check_for_folder_in_google_drive(): + """Checks if folder exists in Google Drive else create it.""" def _create_folder_in_google_drive(google_drive, account): file_metadata = { "name": account.backup_folder_name, @@ -135,42 +140,33 @@ def create_folder_in_google_drive(): try: folder = google_drive.files().create(body=file_metadata, fields="id").execute() frappe.db.set_value("Google Drive", None, "backup_folder_id", folder.get("id")) + frappe.db.commit() except HttpError as e: frappe.throw(_("Google Drive - Could not create folder in Google Drive - Error Code {0}").format(e)) google_drive, account = get_google_drive_object() + + if account.backup_folder_id: + return + backup_folder_exists = False try: - folder_exists = google_drive.files().list(q="mimeType='application/vnd.google-apps.folder'".format(account.backup_folder_name)).execute().get("files", []) + google_drive_folders = google_drive.files().list(q="mimeType='application/vnd.google-apps.folder'".format(account.backup_folder_name)).execute().get("files", []) except HttpError as e: frappe.throw(_("Google Drive - Could not find folder in Google Drive - Error Code {0}").format(e)) - if folder_exists: - for f in folder_exists: + if google_drive_folders: + for f in google_drive_folders: if f.get("name") == account.backup_folder_name: frappe.db.set_value("Google Drive", None, "backup_folder_id", f.get("id")) + frappe.db.commit() backup_folder_exists = True break if not backup_folder_exists: _create_folder_in_google_drive(google_drive, account) - return _("Folder Created in Google Drive.") - -def check_for_folder_in_google_drive(google_drive, account): - """ - Create a folder on Drive, returns the newely created folders ID - """ - if not account.backup_folder_id: - create_folder_in_google_drive() - return - - try: - google_drive.files().get(fileId=account.backup_folder_id, fields="id").execute() - except HttpError as e: - frappe.throw(_("Google Drive - Could not find folder in Google Drive - Error Code {0}.").format(e)) - @frappe.whitelist() def take_backup(): """Enqueue longjob for taking backup to Google Drive""" @@ -185,8 +181,9 @@ def upload_system_backup_to_google_drive(): google_drive, account = get_google_drive_object() # Check if folder exists in Google Drive - check_for_folder_in_google_drive(google_drive, account) + check_for_folder_in_google_drive() account.load_from_db() + progress(1, "Backing up Data.") backup = new_backup() From 2373014e11b4718ba888c8fb151491dd18b93fac Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 21 Aug 2019 21:32:16 +0530 Subject: [PATCH 56/58] fix: codacy --- frappe/integrations/doctype/google_drive/google_drive.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index c83165d87f..84e8f98407 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -16,7 +16,7 @@ from frappe.utils import get_request_site_address from frappe.utils.background_jobs import enqueue from six.moves.urllib.parse import quote from apiclient.http import MediaFileUpload -from frappe.utils import get_backups_path, get_files_path, get_bench_path +from frappe.utils import get_backups_path, get_bench_path from frappe.utils.backups import new_backup from frappe.integrations.doctype.google_settings.google_settings import get_auth_url @@ -152,12 +152,12 @@ def check_for_folder_in_google_drive(): backup_folder_exists = False try: - google_drive_folders = google_drive.files().list(q="mimeType='application/vnd.google-apps.folder'".format(account.backup_folder_name)).execute().get("files", []) + google_drive_folders = google_drive.files().list(q="mimeType='application/vnd.google-apps.folder'".format(account.backup_folder_name)).execute() except HttpError as e: frappe.throw(_("Google Drive - Could not find folder in Google Drive - Error Code {0}").format(e)) - if google_drive_folders: - for f in google_drive_folders: + if google_drive_folders.get("files"): + for f in google_drive_folders.get("files"): if f.get("name") == account.backup_folder_name: frappe.db.set_value("Google Drive", None, "backup_folder_id", f.get("id")) frappe.db.commit() From 6ae434c937b5dc5e08100f5781f84c52281dcdb6 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 21 Aug 2019 21:50:40 +0530 Subject: [PATCH 57/58] fix: codacy --- frappe/integrations/doctype/google_drive/google_drive.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index 84e8f98407..9a80a64ed4 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -152,7 +152,7 @@ def check_for_folder_in_google_drive(): backup_folder_exists = False try: - google_drive_folders = google_drive.files().list(q="mimeType='application/vnd.google-apps.folder'".format(account.backup_folder_name)).execute() + google_drive_folders = google_drive.files().list(q="mimeType='application/vnd.google-apps.folder'").execute() except HttpError as e: frappe.throw(_("Google Drive - Could not find folder in Google Drive - Error Code {0}").format(e)) From 2ba5f6e0ac21daee7ac3662594a22ceef2e1d1c8 Mon Sep 17 00:00:00 2001 From: Himanshu Warekar Date: Wed, 21 Aug 2019 23:20:40 +0530 Subject: [PATCH 58/58] fix: remove unnecessary check --- .../doctype/google_drive/google_drive.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/frappe/integrations/doctype/google_drive/google_drive.py b/frappe/integrations/doctype/google_drive/google_drive.py index 9a80a64ed4..8078c702c0 100644 --- a/frappe/integrations/doctype/google_drive/google_drive.py +++ b/frappe/integrations/doctype/google_drive/google_drive.py @@ -156,13 +156,12 @@ def check_for_folder_in_google_drive(): except HttpError as e: frappe.throw(_("Google Drive - Could not find folder in Google Drive - Error Code {0}").format(e)) - if google_drive_folders.get("files"): - for f in google_drive_folders.get("files"): - if f.get("name") == account.backup_folder_name: - frappe.db.set_value("Google Drive", None, "backup_folder_id", f.get("id")) - frappe.db.commit() - backup_folder_exists = True - break + for f in google_drive_folders.get("files"): + if f.get("name") == account.backup_folder_name: + frappe.db.set_value("Google Drive", None, "backup_folder_id", f.get("id")) + frappe.db.commit() + backup_folder_exists = True + break if not backup_folder_exists: _create_folder_in_google_drive(google_drive, account)