Error while integration dropbox

When try to integrate dropbox i get error.

The error id getting when i click Allow drop box access.

the error is as follows

Traceback (most recent call last):
  File "/home/shahid/thinksmart_new/frappe-bench/apps/frappe/frappe/app.py", line 55, in application
    response = frappe.handler.handle()
  File "/home/shahid/thinksmart_new/frappe-bench/apps/frappe/frappe/handler.py", line 19, in handle
    execute_cmd(cmd)
  File "/home/shahid/thinksmart_new/frappe-bench/apps/frappe/frappe/handler.py", line 40, in execute_cmd
    ret = frappe.call(method, **frappe.form_dict)
  File "/home/shahid/thinksmart_new/frappe-bench/apps/frappe/frappe/__init__.py", line 898, in call
    return fn(*args, **newargs)
  File "/home/shahid/thinksmart_new/frappe-bench/apps/frappe/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py", line 110, in get_dropbox_authorize_url
    sess = doc.get_dropbox_session()
  File "/home/shahid/thinksmart_new/frappe-bench/apps/frappe/frappe/integrations/doctype/dropbox_settings/dropbox_settings.py", line 62, in get_dropbox_session
    sess = session.DropboxSession(app_access_key, app_secret_key, "app_folder")
AttributeError: 'module' object has no attribute 'DropboxSession'
Report this issue

so i installed session module via

sudo pip install dropbox

but i get same error now can anyone help me to find what i am missing

Hello,
Can you try this method?

@fnrfarid i can’t try this because in the video i has 10 field

in my local i can see only 8 fields.

@fnrfarid can you help me with this

Oops! Sorry about that. I’m a newbie too. Hope someone else will chip in.

@fnrfarid no problem

and thanks for the link you given

that’s also informative

you need dropbox in frappe-bench’s virtual environment, bench update generally takes care of updating requirements.txt

try this

~$ cd ~/frappe-bench
~/frappe-bench $ ./env/bin/pip install dropbox

Hello, @revant_one

I’m having this errors. I’m trying to integrate Dropbox with this method Can you help me out?
N.B: I was able to integrate Dropbox by this method on another site on another server.

Traceback (most recent call last):
File “/home/frappe/frappe-bench/apps/frappe/frappe/desk/form/save.py”, line 22, in savedocs
doc.save()
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 256, in save
return self._save(*args, **kwargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 293, in _save
self._validate()
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 442, in _validate
self._save_passwords()
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py”, line 625, in _save_passwords
set_encrypted_password(self.doctype, self.name, new_password, df.fieldname)
File “/home/frappe/frappe-bench/apps/frappe/frappe/utils/password.py”, line 25, in set_encrypted_password
{ ‘doctype’: doctype, ‘name’: name, ‘fieldname’: fieldname, ‘pwd’: encrypt(pwd) })
File “/home/frappe/frappe-bench/apps/frappe/frappe/utils/password.py”, line 95, in encrypt
cipher_suite = Fernet(encode(get_encryption_key()))
File “/home/frappe/frappe-bench/apps/frappe/frappe/utils/password.py”, line 113, in get_encryption_key
update_site_config(‘encryption_key’, encryption_key)
File “/home/frappe/frappe-bench/apps/frappe/frappe/installer.py”, line 294, in update_site_config
with open(site_config_path, “w”) as f:
IOError: [Errno 13] Permission denied: u’./farid.excelbd.com/site_config.json’

Traceback (most recent call last):
File “/home/frappe/frappe-bench/apps/frappe/frappe/app.py”, line 57, in application
response = frappe.handler.handle()
File “/home/frappe/frappe-bench/apps/frappe/frappe/handler.py”, line 22, in handle
data = execute_cmd(cmd)
File “/home/frappe/frappe-bench/apps/frappe/frappe/handler.py”, line 53, in execute_cmd
return frappe.call(method, **frappe.form_dict)
File “/home/frappe/frappe-bench/apps/frappe/frappe/init.py”, line 935, in call
return fn(*args, **newargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/desk/form/save.py”, line 22, in savedocs
doc.save()
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 256, in save
return self._save(*args, **kwargs)
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 293, in _save
self._validate()
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/document.py”, line 442, in _validate
self._save_passwords()
File “/home/frappe/frappe-bench/apps/frappe/frappe/model/base_document.py”, line 625, in _save_passwords
set_encrypted_password(self.doctype, self.name, new_password, df.fieldname)
File “/home/frappe/frappe-bench/apps/frappe/frappe/utils/password.py”, line 25, in set_encrypted_password
{ ‘doctype’: doctype, ‘name’: name, ‘fieldname’: fieldname, ‘pwd’: encrypt(pwd) })
File “/home/frappe/frappe-bench/apps/frappe/frappe/utils/password.py”, line 95, in encrypt
cipher_suite = Fernet(encode(get_encryption_key()))
File “/home/frappe/frappe-bench/apps/frappe/frappe/utils/password.py”, line 113, in get_encryption_key
update_site_config(‘encryption_key’, encryption_key)
File “/home/frappe/frappe-bench/apps/frappe/frappe/installer.py”, line 294, in update_site_config
with open(site_config_path, “w”) as f:
IOError: [Errno 13] Permission denied: u’./farid.excelbd.com/site_config.json’

@revant_one it did’t solved my error

refer this

In new version, you just need three field,
App Access Key
App Secret Key
Dropbox Access Token

Note: Dropbox Access Token is hidden, so you need to remove hidden property.

@kolate_sambhaji

Which version of frappe/ERPNext are you using?

1 Like

@saurabh6790 my version is

__version__ = '7.2.29'

Basically, dropbox has deprecated V1 API’s and launched V2 API’s.

From ERPNext/Frappe v8, we have added support for Dropbox V2 API’s. Please upgrade your ERPNext to V8.x.x or V9 (first take backup of v7)

@saurabh6790 i fixed the issue.

but i have a doubt how the the files are uploaded

do same files upload daily or only new file add to drop box daily

more elaborately

consider in my_site.loc(my site name) directory

i have a file 22.png in above directory/public

when scheduler runs it will upload 22.png in dropbox

and tomorrow i added another file 23.png in same directoy

now which files are added to dropbox

do both will upload or only new one(23.png) gets upload in dropbox

pardon me if not clear

thanks

# Copyright (c) 2015, Frappe Technologies and contributors
# For license information, please see license.txt

from __future__ import unicode_literals
import frappe
import os
from frappe import _
from frappe.utils.backups import new_backup
from frappe.utils.background_jobs import enqueue
from frappe.utils import (cint, split_emails, get_request_site_address, cstr,
	get_files_path, get_backups_path, encode)
from frappe.integration_broker.doctype.integration_service.integration_service import IntegrationService
import sys
import dropbox
from dropbox.files import WriteMode
from dropbox.exceptions import ApiError, AuthError

ignore_list = [".DS_Store"]

class DropboxSettings(IntegrationService):
	scheduler_events = {
		"daily_long": [
			"frappe.integrations.doctype.dropbox_settings.dropbox_settings.take_backups_daily"
		],
		"weekly_long": [
			"frappe.integrations.doctype.dropbox_settings.dropbox_settings.take_backups_weekly"
		]
	}

	def onload(self):
		if not self.app_access_key and frappe.conf.dropbox_access_key:
			self.dropbox_setup_via_site_config = 1

	def validate(self):
		if not self.flags.ignore_mandatory:
			self.validate_dropbox_credentails()

	def on_update(self):
		pass

	def enable(self):
		""" enable service """
		if not self.flags.ignore_mandatory:
			self.validate_dropbox_credentails()

	def validate_dropbox_credentails(self):
		try:
			self.get_dropbox_session()
		except Exception, e:
			frappe.throw(e.message)

	def get_dropbox_session(self):
		# try:
		# 	from dropbox import session
		# except:
		# 	raise Exception(_("Please install dropbox python module"))

		app_access_key = self.app_access_key or frappe.conf.dropbox_access_key
		# app_secret_key = self.get_password(fieldname="app_secret_key",
		# 	raise_exception=False) if self.app_secret_key else frappe.conf.dropbox_secret_key

		if not (app_access_key):
			raise Exception(_("Please set Dropbox access keys in your site config"))

		dbx = dropbox.Dropbox(app_access_key)
		try:
			dbx.users_get_current_account()
		except AuthError as err:
			sys.exit("ERROR: Invalid access token; try re-generating an "
				"access token from the app console on the web.")
		# sess = session.DropboxSession(app_access_key, app_secret_key, "app_folder")

		return app_access_key

@frappe.whitelist()
def get_service_details():
	return """
	<div>
		Steps to enable dropbox backup service:
		<ol>
			<li> Create a dropbox app then get App Key and App Secret,
				<a href="https://www.dropbox.com/developers/apps" target="_blank">
					https://www.dropbox.com/developers/apps
				</a>
			</li>
			<br>
			<li> Setup credentials on Dropbox Settings doctype.
				Click on
				<button class="btn btn-default btn-xs disabled"> Dropbox Settings </button>
				top right corner
			</li>
			<br>
			<li> After settings up App key and App Secret, generate access token
				<button class="btn btn-default btn-xs disabled"> Allow Dropbox Access </button>
			</li>
			<br>
			<li>
				After saving settings,
					<label>
						<span class="input-area">
							<input type="checkbox" class="input-with-feedback" checked disabled>
						</span>
						<span class="label-area small">Enable</span>
					</label>
				Dropbox Integration Service and Save a document.
			</li>
		</ol>
		<p>
			After enabling service, system will take backup of files and database on daily or weekly basis
			as per set on Dropbox Settings page and upload it to your dropbox.
		</p>
	</div>
	"""

#get auth token
@frappe.whitelist()
def get_dropbox_authorize_url():
	doc = frappe.get_doc("Dropbox Settings")
	sess = doc.get_dropbox_session()
	# request_token = sess.obtain_request_token()

	doc.update({
		"dropbox_access_key": sess,
		# "dropbox_access_secret": request_token.secret
	})

	doc.save(ignore_permissions=False)

	return_address = get_request_site_address(True) \
		+ "?cmd=frappe.integrations.doctype.dropbox_settings.dropbox_settings.dropbox_callback"

	# url = sess.build_authorize_url(request_token, return_address)

	return {
		"url": doc.doctype+"/"+doc.name,
	}

@frappe.whitelist(allow_guest=True)
def dropbox_callback(oauth_token=None, not_approved=False):
	doc = frappe.get_doc("Dropbox Settings")
	close = '<p class="text-muted">' + _('Please close this window') + '</p>'

	if not not_approved:
		if doc.get_password(fieldname="dropbox_access_key", raise_exception=False)==oauth_token:
			sess = doc.get_dropbox_session()
			sess.set_request_token(doc.get_password(fieldname="dropbox_access_key", raise_exception=False),
				doc.get_password(fieldname="dropbox_access_secret", raise_exception=False))

			access_token = sess.obtain_access_token()

			frappe.db.set_value("Dropbox Settings", None, "dropbox_access_key", access_token.key)
			frappe.db.set_value("Dropbox Settings", None, "dropbox_access_secret", access_token.secret)

			frappe.db.commit()
		else:
			frappe.respond_as_web_page(_("Dropbox Setup"),
				_("Illegal Access Token. Please try again") + close,
				success=False, http_status_code=frappe.AuthenticationError.http_status_code)
	else:
		frappe.respond_as_web_page(_("Dropbox Setup"),
			_("You did not apporve Dropbox Access.") + close,
			success=False, http_status_code=frappe.AuthenticationError.http_status_code)

	frappe.respond_as_web_page(_("Dropbox Setup"),
		_("Dropbox access is approved!") + close,
		success=False, http_status_code=frappe.AuthenticationError.http_status_code)

# backup process
@frappe.whitelist()
def take_backup():
	"Enqueue longjob for taking backup to dropbox"
	enqueue("frappe.integrations.doctype.dropbox_settings.dropbox_settings.take_backup_to_dropbox", queue='long')
	frappe.msgprint(_("Queued for backup. It may take a few minutes to an hour."))

def take_backups_daily():
	take_backups_if("Daily")

def take_backups_weekly():
	take_backups_if("Weekly")

def take_backups_if(freq):
	if frappe.db.get_value("Dropbox Settings", None, "backup_frequency") == freq:
		take_backup_to_dropbox()

def take_backup_to_dropbox():
	did_not_upload, error_log = [], []
	try:
		if cint(frappe.db.get_value("Integration Service", "Dropbox", "enabled")):
			did_not_upload, error_log = backup_to_dropbox()
			if did_not_upload: raise Exception

			send_email(True, "Dropbox")
	except Exception:
		file_and_error = [" - ".join(f) for f in zip(did_not_upload, error_log)]
		error_message = ("\n".join(file_and_error) + "\n" + frappe.get_traceback())
		frappe.errprint(error_message)
		send_email(False, "Dropbox", error_message)

def send_email(success, service_name, error_status=None):
	if success:
		subject = "Backup Upload Successful"
		message ="""<h3>Backup Uploaded Successfully</h3><p>Hi there, this is just to inform you
		that your backup was successfully uploaded to your %s account. So relax!</p>
		""" % service_name

	else:
		subject = "[Warning] Backup Upload Failed"
		message ="""<h3>Backup Upload Failed</h3><p>Oops, your automated backup to %s
		failed.</p>
		<p>Error message: <br>
		<pre><code>%s</code></pre>
		</p>
		<p>Please contact your system manager for more information.</p>
		""" % (service_name, error_status)

	if not frappe.db:
		frappe.connect()

	recipients = split_emails(frappe.db.get_value("Dropbox Settings", None, "send_notifications_to"))
	frappe.sendmail(recipients=recipients, subject=subject, message=message)

def backup_to_dropbox(): 
	if not frappe.db:
		frappe.connect()

	dropbox_client = get_dropbox_client()
	# upload database
	backup = new_backup(ignore_files=True)
	filename = os.path.join(get_backups_path(), os.path.basename(backup.backup_path_db))
	upload_file_to_dropbox(filename, "/database", dropbox_client)

	frappe.db.close()

	# upload files to files folder
	did_not_upload = []
	error_log = []
	print get_files_path()
	upload_from_folder(get_files_path(), "/files", dropbox_client,did_not_upload,error_log)
	upload_from_folder(get_files_path(is_private=1), "/private/files", dropbox_client,did_not_upload,error_log)

	frappe.connect()
	print did_not_upload
	return did_not_upload, list(set(error_log))

def get_dropbox_client(previous_dropbox_client=None):
	# from dropbox import client
	doc = frappe.get_doc("Dropbox Settings")
	sess = doc.get_dropbox_session()

	# sess.set_token(doc.get_password(fieldname="dropbox_access_key", raise_exception=False),
	# 	doc.get_password(fieldname="dropbox_access_secret", raise_exception=False))

	dropbox_client = dropbox.Dropbox(sess)

	# upgrade to oauth2
	# token = dropbox_client.create_oauth2_access_token()
	# dropbox_client = client.DropboxClient(token)
	# if previous_dropbox_client:
	# 	dropbox_client.connection_reset_count = previous_dropbox_client.connection_reset_count + 1
	# else:
	# 	dropbox_client.connection_reset_count = 0
	return dropbox_client

def upload_file_to_dropbox(filename, folder, dropbox_client):
	create_folder_if_not_exists(folder, dropbox_client)
	chunk_size = 4 * 1024 * 1024
	file_size = os.path.getsize(encode(filename))
	mode = (dropbox.files.WriteMode.overwrite)

	f = open(encode(filename), 'rb')
	path = "{0}/{1}".format(folder, os.path.basename(filename))

	try:
		if file_size <= chunk_size:
			dropbox_client.files_upload(f.read(), path, mode)
		else:
			upload_session_start_result = dropbox_client.files_upload_session_start(f.read(chunk_size))
			cursor = dropbox.files.UploadSessionCursor(session_id=upload_session_start_result.session_id, offset=f.tell())
			commit = dropbox.files.CommitInfo(path=path, mode=mode)

			while f.tell() < file_size:
				if ((file_size - f.tell()) <= chunk_size):
					dropbox_client.files_upload_session_finish(f.read(chunk_size), cursor, commit)
				else:
					dropbox_client.files_upload_session_append(f.read(chunk_size), cursor.session_id,cursor.offset)
					cursor.offset = f.tell()
	except dropbox.exceptions.ApiError as e:
		if isinstance(e.error, dropbox.files.UploadError):
			error = "File Path: {path}\n".foramt(path=path)
			error += frappe.get_traceback()
			frappe.log_error(error)
		else:
			raise


def create_folder_if_not_exists(folder, dropbox_client):
	try:
		dropbox_client.files_get_metadata(folder)
	except dropbox.exceptions.ApiError as e:
		# folder not found
		if isinstance(e.error, dropbox.files.GetMetadataError):
			dropbox_client.files_create_folder(folder)
		else:
			raise


def upload_from_folder(path, dropbox_folder, dropbox_client, did_not_upload, error_log):
	if not os.path.exists(path):
		return

	try:
		response = dropbox_client.files_list_folder(dropbox_folder)
	except dropbox.exceptions.ApiError as e:
		# folder not found
		if isinstance(e.error, dropbox.files.ListFolderError):
			response = frappe._dict({"entries": []})
		else:
			raise

	for root, directory, files in os.walk(path):
		for filename in files:
			filename = cstr(filename)
			filepath = os.path.join(root, filename)

			if filename in ignore_list:
				continue

			found = False
			for file_metadata in response.entries:
				if (os.path.basename(filepath) == file_metadata.name
					and os.stat(encode(filepath)).st_size == int(file_metadata.size)):
					found = True
					break

			if not found:
				try:
					upload_file_to_dropbox(filepath, dropbox_folder, dropbox_client)
				except Exception:
					did_not_upload.append(filepath)
					error_log.append(frappe.get_traceback())

i solved the problem using above code

thanks for your help