ERPNext Foundation ERPNext Cloud Chat Blog Discuss Frappé* Donate

Private files not accessible to Customer on Web Portal

files

#1

Use case : To allow access to private files to Customers role ,but not to anyone having the file URL.

At present if a file is private it is accessible to all the roles having Desk access on the web portal.

How to allow access on web portal for the private files to Customer role , not having desk access.

Is this a bug or functionality or is there any workaround ?


#2

Bumping this thread… We have a need for the same use case. Hope someone can suggest a solution.


#3

Update on this: the following is the solution we came up with for this particular use case.

We just created this whitelisted python function:

import frappe, os, urlparse

@frappe.whitelist(allow_guest=True)
def view_attachment(file_name, user):
	if not user == frappe.session.user:
		frappe.msgprint("Session error.", indicator="red")
	user = frappe.get_doc("User", user)
	if not user:
		frappe.throw("Authorization error.")
	cwd = os.getcwd()
	attachment = frappe.get_doc("File", file_name)
	if attachment:
		file_name = attachment.get('file_name')
		file_url  = attachment.get('file_url')
		if not file_name and is_in_erp( file_url ): # to handle web url attachments
			parsed_url = urlparse( file_url )
			file_url   = parsed_url.path
			file_name  = "Attachment"
		if is_public_file( file_url ):
			file_path = cwd + "/our.erpinstance.tld/public" + file_url
		else:
			file_path = cwd + "/our.erpinstance.tld" + file_url
	else:
		frappe.throw("File not found.")
	with open(file_path, "rb") as fileobj:
		filedata = fileobj.read()
	frappe.local.response.filename = file_name
	frappe.local.response.filecontent = filedata
	frappe.local.response.type = "download"

def is_public_file(file_path):
	if file_path[0:7] == "/files/":
		return True
	else:
		return False

def is_in_erp(a_url):
	parsed_url = urlparse(a_url)
	if parsed_url.netloc == 'our.erpinstance.tld':
		return True
	else:
		return False

And for the website users to view private files, you then just have to link to the file this way:

(JS)

var request_url = "/api/method/dotted.path.to.your.pymodule.view_attachment"
                + "?file_name="+encodeURIComponent("File Name Here")
                + "&user="+encodeURIComponent(frappe.session.user);

(HTML)

<a href="{{ request_url }}" target="_blank">File Name Here</a>

Hope this helps.


#4

Another solution is to temporarily update session. link