diff --git a/frappe/templates/includes/list/list.js b/frappe/templates/includes/list/list.js index 467e2cdad7..2d31eda1a5 100644 --- a/frappe/templates/includes/list/list.js +++ b/frappe/templates/includes/list/list.js @@ -9,7 +9,8 @@ frappe.ready(function() { doctype: "{{ doctype }}", txt: "{{ txt or '' }}", limit_start: next_start, - pathname: location.pathname + pathname: location.pathname, + is_web_form: "{{ is_web_form }}" }); btn.prop("disabled", true); diff --git a/frappe/templates/includes/list/row_template.html b/frappe/templates/includes/list/row_template.html index 65fa99305c..599d4f88ac 100644 --- a/frappe/templates/includes/list/row_template.html +++ b/frappe/templates/includes/list/row_template.html @@ -1,7 +1,10 @@ {% set doc = frappe.get_doc(doc) %} {% set subject = doc.get(meta.title_field or "name") %} +{% set route = ((is_web_form is defined and is_web_form and "{0}?name={1}".format(pathname, doc.name)) + or (doc.get("get_route") and doc.get_route()) + or "{0}/{1}".format(pathname or doc.doctype, doc.name)) %}
- +

{{ subject }}

diff --git a/frappe/templates/pages/list.py b/frappe/templates/pages/list.py index ee227ff72b..ee0f3c6ca0 100644 --- a/frappe/templates/pages/list.py +++ b/frappe/templates/pages/list.py @@ -27,18 +27,7 @@ def get(doctype, txt=None, limit_start=0, **kwargs): limit_page_length = 20 next_start = limit_start + limit_page_length - filters = frappe._dict(kwargs) - if filters.pathname: - # resolve additional filters from path - resolve_path(filters.pathname) - for key, val in frappe.local.form_dict.items(): - if key in ("cmd", "pathname", "doctype", "txt", "limit_start"): - if key in filters: - del filters[key] - - elif key not in filters: - filters[key] = val - + filters = prepare_filters(kwargs) meta = frappe.get_meta(doctype) list_context = get_list_context({}, doctype) @@ -73,13 +62,41 @@ def get(doctype, txt=None, limit_start=0, **kwargs): "next_start": next_start } +def prepare_filters(kwargs): + filters = frappe._dict(kwargs) + + if filters.pathname: + # resolve additional filters from path + resolve_path(filters.pathname) + for key, val in frappe.local.form_dict.items(): + if key in ("cmd", "pathname", "doctype", "txt", "limit_start"): + if key in filters: + del filters[key] + + elif key not in filters: + filters[key] = val + + if "is_web_form" in filters: + del filters["is_web_form"] + + return filters + def get_list_context(context, doctype): from frappe.modules import load_doctype_module + from frappe.website.doctype.web_form.web_form import get_web_form_list + + list_context = frappe._dict() module = load_doctype_module(doctype) if hasattr(module, "get_list_context"): - return frappe._dict(module.get_list_context(context) or {}) + list_context = frappe._dict(module.get_list_context(context) or {}) - return frappe._dict() + # is web form + if cint(frappe.local.form_dict.is_web_form): + list_context.is_web_form = 1 + if not list_context.get("get_list"): + list_context.get_list = get_web_form_list + + return list_context def get_list(doctype, txt, filters, limit_start, limit_page_length=20, ignore_permissions=False): meta = frappe.get_meta(doctype) diff --git a/frappe/website/doctype/web_form/web_form.py b/frappe/website/doctype/web_form/web_form.py index 4e098ed5c8..a715686cbd 100644 --- a/frappe/website/doctype/web_form/web_form.py +++ b/frappe/website/doctype/web_form/web_form.py @@ -7,7 +7,6 @@ from frappe.website.website_generator import WebsiteGenerator from frappe import _ from frappe.utils.file_manager import save_file, remove_file_by_url from frappe.website.utils import get_comment_list -from frappe.templates.pages.list import get_context as get_list_context class WebForm(WebsiteGenerator): website = frappe._dict( @@ -18,8 +17,20 @@ class WebForm(WebsiteGenerator): ) def get_context(self, context): + from frappe.templates.pages.list import get_context as get_list_context + + frappe.local.form_dict.is_web_form = 1 context.params = frappe.form_dict - if self.login_required and frappe.session.user != "Guest": + logged_in = frappe.session.user != "Guest" + + # check permissions + if not logged_in and frappe.form_dict.name: + frappe.throw(_("You need to be logged in to access this {0}.").format(self.doc_type), frappe.PermissionError) + + if frappe.form_dict.name and not has_web_form_permission(self.doc_type, frappe.form_dict.name): + frappe.throw(_("You don't have the permissions to access this document"), frappe.PermissionError) + + if self.login_required and logged_in: if self.allow_edit: if self.allow_multiple: if not context.params.name and not context.params.new: @@ -27,11 +38,14 @@ class WebForm(WebsiteGenerator): get_list_context(context) context.is_list = True else: - name = frappe.db.get_value(self.doc_type, {"owner": frappe.session.user}, - "name") + name = frappe.db.get_value(self.doc_type, {"owner": frappe.session.user}, "name") if name: frappe.form_dict.name = name + # always render new form if login is not required or doesn't allow editing existing ones + if not self.login_required or not self.allow_edit: + frappe.form_dict.new = 1 + if frappe.form_dict.name or frappe.form_dict.new: context.layout = self.get_layout() context.parents = [{"name": self.get_route(), "title": self.title }] @@ -78,6 +92,9 @@ def accept(): if args.doctype != web_form.doc_type: frappe.throw(_("Invalid Request")) + elif args.name and not web_form.allow_edit: + frappe.throw(_("You are not allowed to update this Web Form Document")) + if args.name: # update doc = frappe.get_doc(args.doctype, args.name) @@ -101,7 +118,7 @@ def accept(): doc.set(fieldname, value) if args.name: - if doc.owner==frappe.session.user: + if has_web_form_permission(doc.doctype, doc.name, "write"): doc.save(ignore_permissions=True) else: # only if permissions are present @@ -141,3 +158,26 @@ def delete(web_form, name): frappe.delete_doc(web_form.doc_type, name, ignore_permissions=True) else: raise frappe.PermissionError, "Not Allowed" + +def has_web_form_permission(doctype, name, ptype='read'): + if frappe.session.user=="Guest": + return False + + # owner matches + elif frappe.db.get_value(doctype, name, "owner")==frappe.session.user: + return True + + elif frappe.has_website_permission(doctype, ptype=ptype, doc=name): + return True + + else: + return False + +def get_web_form_list(doctype, txt, filters, limit_start, limit_page_length=20): + from frappe.templates.pages.list import get_list + if not filters: + filters = {} + + filters["owner"] = frappe.session.user + + return get_list(doctype, txt, filters, limit_start, limit_page_length, ignore_permissions=True)