From ae68ad53a7778dc6df97d887ef2c5bacaea66d5e Mon Sep 17 00:00:00 2001 From: Aradhya Date: Sat, 20 Nov 2021 23:51:06 +0530 Subject: [PATCH] feat: Added permissions to database API --- frappe/database/database.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/frappe/database/database.py b/frappe/database/database.py index 6de8c9e72a..6d6ed467b6 100644 --- a/frappe/database/database.py +++ b/frappe/database/database.py @@ -116,6 +116,10 @@ class Database(object): if not run: return query + if not kwargs.get("ignore_permissions", True): + tables = self.get_tables_from_query(query) + self.check_permissions(doctype=tables, **kwargs) + if re.search(r'ifnull\(', query, flags=re.IGNORECASE): # replaces ifnull in query with coalesce query = re.sub(r'ifnull\(', 'coalesce(', query, flags=re.IGNORECASE) @@ -260,6 +264,24 @@ class Database(object): self.commit() self.sql(query, debug=debug) + @staticmethod + def check_permissions(doctype, **kwargs): + kwargs.pop("ignore_permissions") + if isinstance(doctype, str): + doctype = [doctype] + + for dt in doctype: + dt = re.sub("tab", "", dt) + if not frappe.has_permission( + dt, "select", **kwargs + ) and not frappe.has_permission(dt, "read", **kwargs): + frappe.flags.error_message = _('Insufficient Permission for {0}').format(frappe.bold(dt)) + raise frappe.PermissionError(dt) + + @staticmethod + def get_tables_from_query(query: str): + return [table for table in re.findall(r"\w+", query) if table.startswith("tab")] + def check_transaction_status(self, query): """Raises exception if more than 20,000 `INSERT`, `UPDATE` queries are executed in one transaction. This is to ensure that writes are always flushed otherwise this