def update_user_permissions(self): if not self.create_user_permission: return if not has_permission( 'User Permission', ptype='write', raise_exception=False): return employee_user_permission_exists = frappe.db.exists( 'User Permission', { 'allow': 'Employee', 'for_value': self.name, 'user': self.user_id }) if employee_user_permission_exists: return employee_user_permission_exists = frappe.db.exists( 'User Permission', { 'allow': 'Employee', 'for_value': self.name, 'user': self.user_id }) if employee_user_permission_exists: return add_user_permission("Employee", self.name, self.user_id) set_user_permission_if_allowed("Company", self.company, self.user_id)
def update_user_permissions(doc, method): # called via User hook if "Employee" in [d.role for d in doc.get("roles")]: if not has_permission( 'User Permission', ptype='write', raise_exception=False): return employee = frappe.get_doc("Employee", {"user_id": doc.name}) employee.update_user_permissions()
def filter_allowed_users(users, doc, transition): """Filters list of users by checking if user has access to doc and if the user satisfies 'workflow transision self approval' condition """ from frappe.permissions import has_permission filtered_users = [] for user in users: if (has_approval_access(user, doc, transition) and has_permission(doctype=doc, user=user)): filtered_users.append(user) return filtered_users
def filter_allowed_users(users, doc, transition): """Filters list of users by checking if user has access to doc and if the user satisfies 'workflow transision self approval' condition """ from frappe.permissions import has_permission filtered_users = [] for user in users: if (has_approval_access(user, doc, transition) and has_permission(doctype=doc, user=user)): filtered_users.append(user) return filtered_users
def update_user_permissions(self): if not self.create_user_permission: return if not has_permission('User Permission', ptype='write', raise_exception=False): return employee_user_permission_exists = frappe.db.exists('User Permission', { 'allow': 'Employee', 'for_value': self.name, 'user': self.user_id }) if employee_user_permission_exists: return add_user_permission("Employee", self.name, self.user_id) set_user_permission_if_allowed("Company", self.company, self.user_id)
def update_user_permissions(self): if not self.create_user_permission: return if not has_permission( "User Permission", ptype="write", raise_exception=False): return employee_user_permission_exists = frappe.db.exists( "User Permission", { "allow": "Employee", "for_value": self.name, "user": self.user_id }) if employee_user_permission_exists: return add_user_permission("Employee", self.name, self.user_id) set_user_permission_if_allowed("Company", self.company, self.user_id)
def search_widget(doctype, txt, query=None, searchfield=None, start=0, page_length=10, filters=None, filter_fields=None, as_dict=False, reference_doctype=None, ignore_user_permissions=False): if isinstance(filters, string_types): filters = json.loads(filters) if searchfield: sanitize_searchfield(searchfield) if not searchfield: searchfield = "name" standard_queries = frappe.get_hooks().standard_queries or {} if query and query.split()[0].lower() != "select": # by method frappe.response["values"] = frappe.call(query, doctype, txt, searchfield, start, page_length, filters, as_dict=as_dict) elif not query and doctype in standard_queries: # from standard queries search_widget(doctype, txt, standard_queries[doctype][0], searchfield, start, page_length, filters) else: meta = frappe.get_meta(doctype) if query: frappe.throw(_("This query style is discontinued")) # custom query # frappe.response["values"] = frappe.db.sql(scrub_custom_query(query, searchfield, txt)) else: if isinstance(filters, dict): filters_items = filters.items() filters = [] for f in filters_items: if isinstance(f[1], (list, tuple)): filters.append([doctype, f[0], f[1][0], f[1][1]]) else: filters.append([doctype, f[0], "=", f[1]]) if filters == None: filters = [] or_filters = [] # build from doctype if txt: search_fields = ["name"] if meta.title_field: search_fields.append(meta.title_field) if meta.search_fields: search_fields.extend(meta.get_search_fields()) for f in search_fields: fmeta = meta.get_field(f.strip()) if (doctype not in UNTRANSLATED_DOCTYPES) and ( f == "name" or (fmeta and fmeta.fieldtype in [ "Data", "Text", "Small Text", "Long Text", "Link", "Select", "Read Only", "Text Editor" ])): or_filters.append( [doctype, f.strip(), "like", "%{0}%".format(txt)]) if meta.get("fields", { "fieldname": "enabled", "fieldtype": "Check" }): filters.append([doctype, "enabled", "=", 1]) if meta.get("fields", { "fieldname": "disabled", "fieldtype": "Check" }): filters.append([doctype, "disabled", "!=", 1]) # format a list of fields combining search fields and filter fields fields = get_std_fields_list(meta, searchfield or "name") if filter_fields: fields = list(set(fields + json.loads(filter_fields))) formatted_fields = [ '`tab%s`.`%s`' % (meta.name, f.strip()) for f in fields ] # find relevance as location of search term from the beginning of string `name`. used for sorting results. formatted_fields.append( """locate({_txt}, `tab{doctype}`.`name`) as `_relevance`""". format(_txt=frappe.db.escape((txt or "").replace("%", "")), doctype=doctype)) # In order_by, `idx` gets second priority, because it stores link count from frappe.model.db_query import get_order_by order_by_based_on_meta = get_order_by(doctype, meta) # 2 is the index of _relevance column order_by = "2 , {0}, `tab{1}`.idx desc".format( order_by_based_on_meta, doctype) ignore_permissions = True if doctype == "DocType" else ( cint(ignore_user_permissions) and has_permission(doctype)) if doctype in UNTRANSLATED_DOCTYPES: page_length = None values = frappe.get_list(doctype, filters=filters, fields=formatted_fields, or_filters=or_filters, limit_start=start, limit_page_length=page_length, order_by=order_by, ignore_permissions=ignore_permissions, reference_doctype=reference_doctype, as_list=not as_dict) if doctype in UNTRANSLATED_DOCTYPES: values = tuple([ v for v in list(values) if re.search(txt + ".*", ( _(v.name) if as_dict else _(v[0])), re.IGNORECASE) ]) # remove _relevance from results if as_dict: for r in values: r.pop("_relevance") frappe.response["values"] = values else: frappe.response["values"] = [r[:-1] for r in values]
def update_user_permissions(self): if not self.create_user_permission: return if not has_permission('User Permission', ptype='write'): return add_user_permission("Employee", self.name, self.user_id) set_user_permission_if_allowed("Company", self.company, self.user_id)
def update_user_permissions(doc, method): # called via User hook if "Employee" in [d.role for d in doc.get("roles")]: if not has_permission('User Permission', ptype='write'): return employee = frappe.get_doc("Employee", {"user_id": doc.name}) employee.update_user_permissions()
def get_data(): return [ { "module_name": 'Dimension', "category": "Places", "label": _('Dimensions'), "icon": "fa fa-object-ungroup", "type": 'link', "link": '#List/Dimension/List', "color": '#FF4136', 'standard': 1, "condition": has_permission(doctype="Dimension", raise_exception=False) }, { "module_name": 'Product Profile', "category": "Places", "label": _('Product Profiles'), "icon": "fa fa-window-maximize", "type": 'link', "link": '#List/Product Profile/List', "color": '#FF4136', 'standard': 1, "condition": has_permission(doctype="Product Profile", raise_exception=False) }, { "module_name": 'Product Assembly', "category": "Places", "label": _('Product Assemblies'), "icon": "fa fa-product-hunt", "type": 'link', "link": '#List/Product Assembly/List', "color": '#FF4136', 'standard': 1, "condition": has_permission(doctype="Product Assembly", raise_exception=False) }, { "module_name": 'Item', "category": "Places", "label": _('Items'), "icon": "fa fa-codepen", "type": 'link', "link": '#List/Item/List', "color": '#FF4136', 'standard': 1, "condition": has_permission(doctype="Item", raise_exception=False) }, { "module_name": 'Item Group', "category": "Places", "label": _('Item Group'), "icon": "fa fa-indent", "type": 'link', "link": '#Tree/Item Group', "color": '#FF4136', 'standard': 1, "condition": has_permission(doctype="Item Group", raise_exception=False) }, { "module_name": 'Paperboard', "category": "Places", "label": _('Paperboards'), "icon": "fa fa-file-o", "type": 'link', "link": '#List/Paperboard/List', "color": '#FF4136', 'standard': 1, "condition": has_permission(doctype="Paperboard", raise_exception=False) }, { "module_name": 'Cost Estimation', "category": "Places", "label": _('Cost Estimations'), "icon": "fa fa-usd", "type": 'link', "link": '#List/Cost Estimation/List', "color": '#FF4136', 'standard': 1, "condition": has_permission(doctype="Cost Estimation", raise_exception=False) }, { "module_name": 'Compound Product', "category": "Places", "label": _('Compound Products'), "icon": "fa fa-cubes", "type": 'link', "link": '#List/Compound Product/List', "color": '#FF4136', 'standard': 1, "condition": has_permission(doctype="Compound Product", raise_exception=False) }, { "module_name": 'Project Center', "category": "Places", "label": _('Project Centers'), "icon": "fa fa-columns", "type": 'link', "link": '#List/Project Center/List', "color": '#FF4136', 'standard': 1, "condition": has_permission(doctype="Project Center", raise_exception=False) }, { "module_name": 'Task', "category": "Places", "label": _('Task Center'), "icon": "fa fa-tasks", "type": 'link', "link": '#task-center', "color": '#FF4136', 'standard': 1, "condition": has_permission(doctype="Task", raise_exception=False) }, { "module_name": 'Production Planning Tool', "category": "Places", "label": _('Production Planning Tool'), "icon": "fa fa-text-height", "type": 'link', "link": '#List/Production Planning Tool/List', "color": '#FF4136', 'standard': 1, "condition": has_permission(doctype="Production Planning Tool", raise_exception=False) }, { "module_name": 'Recurring Production Planning', "category": "Places", "label": _('Recurring Production Planning'), "icon": "fa fa-superpowers", "type": 'link', "link": '#List/Recurring Production Planning/List', "color": '#FF4136', 'standard': 1, "condition": has_permission(doctype="Recurring Production Planning", raise_exception=False) }, { "module_name": 'Production Order', "category": "Places", "label": _('Production Order'), "icon": "fa fa-cog", "type": 'link', "link": '#List/Production Order/List', "color": '#FF4136', 'standard': 1, "condition": has_permission(doctype="Production Order", raise_exception=False) }, { "module_name": 'Ton Calculation', "category": "Places", "label": _('Ton Calculation'), "icon": "fa fa-industry", "type": 'link', "link": '#Form/Ton Calculation', "color": '#FF4136', 'standard': 1, "condition": has_permission(doctype="Ton Calculation", raise_exception=False) }, { "module_name": 'Die Cut Stocking', "category": "Places", "label": _('Die Cut Stocking'), "icon": "fa fa-stack-overflow", "type": 'link', "link": '#List/Die Cut Stocking/List', "color": '#FF4136', 'standard': 1, "condition": has_permission(doctype="Die Cut Stocking", raise_exception=False) }, { "module_name": 'Material Request', "category": "Places", "label": _('Material Request'), "icon": "fa fa-comments-o", "type": 'link', "link": '#List/Material Request/List', "color": '#FF4136', 'standard': 1, "condition": has_permission(doctype="Material Request", raise_exception=False) }, { "module_name": 'Sales Invoice', "category": "Places", "label": _('Sales Invoice'), "icon": "fa fa-bolt", "type": 'link', "link": '#List/Sales Invoice/List', "color": '#FF4136', 'standard': 1, "condition": has_permission(doctype="Sales Invoice", raise_exception=False) }, { "module_name": 'Customer', "category": "Places", "label": _('Customer'), "icon": "fa fa-users", "type": 'link', "link": '#List/Customer/List', "color": '#FF4136', 'standard': 1, "condition": has_permission(doctype="Customer", raise_exception=False) }, { "module_name": 'Supplier', "category": "Places", "label": _('Supplier'), "icon": "fa fa-address-book-o", "type": 'link', "link": '#List/Supplier/List', "color": '#FF4136', 'standard': 1, "condition": has_permission(doctype="Supplier", raise_exception=False) }, { "module_name": 'Purchase Order', "category": "Places", "label": _('Purchase Order'), "icon": "fa fa-book", "type": 'link', "link": '#List/Purchase Order/List', "color": '#FF4136', 'standard': 1, "condition": has_permission(doctype="Purchase Order", raise_exception=False) }, { "module_name": 'Payment Entry', "category": "Places", "label": _('Payment Entry'), "icon": "fa fa-money", "type": 'link', "link": '#List/Payment Entry/List', "color": '#FF4136', 'standard': 1, "condition": has_permission(doctype="Payment Entry", raise_exception=False) }, { "module_name": 'Reminder', "category": "Places", "label": _('Reminders'), "icon": "fa fa-bell", "type": 'link', "link": '#reminders', "color": '#FF4136', 'standard': 1, "condition": has_permission(doctype="Reminder", raise_exception=False) }, { "module_name": 'Payment Entry Request', "category": "Places", "label": _('Payment Entry Requests'), "icon": "fa fa-credit-card", "type": 'link', "link": '#List/Payment Entry Request/List', "color": '#FF4136', 'standard': 1, "condition": has_permission(doctype="Payment Entry Request", raise_exception=False) }, { "module_name": 'Purchase Invoice', "category": "Places", "label": _('Purchase Invoices'), "icon": "fa fa-building-o", "type": 'link', "link": '#List/Purchase Invoice/List', "color": '#FF4136', 'standard': 1, "condition": has_permission(doctype="Purchase Invoice", raise_exception=False) }, { "module_name": 'Item Description', "category": "Places", "label": _('Item Descriptions'), "icon": "fa fa-dot-circle-o", "type": 'link', "link": '#List/Item Description/List', "color": '#FF4136', 'standard': 1, "condition": has_permission(doctype="Purchase Invoice", raise_exception=False) }, ]
def update_user_permissions(self): if not self.create_user_permission: return if not has_permission('User Permission', ptype='write'): return add_user_permission("Employee", self.name, self.user_id) set_user_permission_if_allowed("Company", self.company, self.user_id)
def search_widget(doctype, txt, query=None, searchfield=None, start=0, page_length=10, filters=None, filter_fields=None, as_dict=False, reference_doctype=None, ignore_user_permissions=False): if isinstance(filters, string_types): filters = json.loads(filters) if searchfield: sanitize_searchfield(searchfield) if not searchfield: searchfield = "name" standard_queries = frappe.get_hooks().standard_queries or {} if query and query.split()[0].lower()!="select": # by method frappe.response["values"] = frappe.call(query, doctype, txt, searchfield, start, page_length, filters, as_dict=as_dict) elif not query and doctype in standard_queries: # from standard queries search_widget(doctype, txt, standard_queries[doctype][0], searchfield, start, page_length, filters) else: meta = frappe.get_meta(doctype) if query: frappe.throw(_("This query style is discontinued")) # custom query # frappe.response["values"] = frappe.db.sql(scrub_custom_query(query, searchfield, txt)) else: if isinstance(filters, dict): filters_items = filters.items() filters = [] for f in filters_items: if isinstance(f[1], (list, tuple)): filters.append([doctype, f[0], f[1][0], f[1][1]]) else: filters.append([doctype, f[0], "=", f[1]]) if filters==None: filters = [] or_filters = [] # build from doctype if txt: search_fields = ["name"] if meta.title_field: search_fields.append(meta.title_field) if meta.search_fields: search_fields.extend(meta.get_search_fields()) for f in search_fields: fmeta = meta.get_field(f.strip()) if (doctype not in UNTRANSLATED_DOCTYPES) and (f == "name" or (fmeta and fmeta.fieldtype in ["Data", "Text", "Small Text", "Long Text", "Link", "Select", "Read Only", "Text Editor"])): or_filters.append([doctype, f.strip(), "like", "%{0}%".format(txt)]) if meta.get("fields", {"fieldname":"enabled", "fieldtype":"Check"}): filters.append([doctype, "enabled", "=", 1]) if meta.get("fields", {"fieldname":"disabled", "fieldtype":"Check"}): filters.append([doctype, "disabled", "!=", 1]) # format a list of fields combining search fields and filter fields fields = get_std_fields_list(meta, searchfield or "name") if filter_fields: fields = list(set(fields + json.loads(filter_fields))) formatted_fields = ['`tab%s`.`%s`' % (meta.name, f.strip()) for f in fields] # find relevance as location of search term from the beginning of string `name`. used for sorting results. formatted_fields.append("""locate("{_txt}", `tab{doctype}`.`name`) as `_relevance`""".format( _txt=frappe.db.escape((txt or "").replace("%", "")), doctype=frappe.db.escape(doctype))) # In order_by, `idx` gets second priority, because it stores link count from frappe.model.db_query import get_order_by order_by_based_on_meta = get_order_by(doctype, meta) order_by = "if(_relevance, _relevance, 99999), {0}, `tab{1}`.idx desc".format(order_by_based_on_meta, doctype) ignore_permissions = True if doctype == "DocType" else (cint(ignore_user_permissions) and has_permission(doctype)) if doctype in UNTRANSLATED_DOCTYPES: page_length = None values = frappe.get_list(doctype, filters=filters, fields=formatted_fields, or_filters=or_filters, limit_start=start, limit_page_length=page_length, order_by=order_by, ignore_permissions=ignore_permissions, reference_doctype=reference_doctype, as_list=not as_dict) if doctype in UNTRANSLATED_DOCTYPES: values = tuple([v for v in list(values) if re.search(txt+".*", (_(v.name) if as_dict else _(v[0])), re.IGNORECASE)]) # remove _relevance from results if as_dict: for r in values: r.pop("_relevance") frappe.response["values"] = values else: frappe.response["values"] = [r[:-1] for r in values]
def search_widget( doctype, txt, query=None, searchfield=None, start=0, page_length=20, filters=None, filter_fields=None, as_dict=False, reference_doctype=None, ignore_user_permissions=False, ): start = cint(start) if isinstance(filters, string_types): filters = json.loads(filters) if searchfield: sanitize_searchfield(searchfield) if not searchfield: searchfield = "name" standard_queries = frappe.get_hooks().standard_queries or {} if query and query.split()[0].lower() != "select": # by method try: is_whitelisted(frappe.get_attr(query)) frappe.response["values"] = frappe.call( query, doctype, txt, searchfield, start, page_length, filters, as_dict=as_dict ) except frappe.exceptions.PermissionError as e: if frappe.local.conf.developer_mode: raise e else: frappe.respond_as_web_page( title="Invalid Method", html="Method not found", indicator_color="red", http_status_code=404 ) return except Exception as e: raise e elif not query and doctype in standard_queries: # from standard queries search_widget( doctype, txt, standard_queries[doctype][0], searchfield, start, page_length, filters ) else: meta = frappe.get_meta(doctype) if query: frappe.throw(_("This query style is discontinued")) # custom query # frappe.response["values"] = frappe.db.sql(scrub_custom_query(query, searchfield, txt)) else: if isinstance(filters, dict): filters_items = filters.items() filters = [] for f in filters_items: if isinstance(f[1], (list, tuple)): filters.append([doctype, f[0], f[1][0], f[1][1]]) else: filters.append([doctype, f[0], "=", f[1]]) if filters == None: filters = [] or_filters = [] translated_search_doctypes = frappe.get_hooks("translated_search_doctypes") # build from doctype if txt: search_fields = ["name"] if meta.title_field: search_fields.append(meta.title_field) if meta.search_fields: search_fields.extend(meta.get_search_fields()) for f in search_fields: fmeta = meta.get_field(f.strip()) if (doctype not in translated_search_doctypes) and ( f == "name" or ( fmeta and fmeta.fieldtype in ["Data", "Text", "Small Text", "Long Text", "Link", "Select", "Read Only", "Text Editor"] ) ): or_filters.append([doctype, f.strip(), "like", "%{0}%".format(txt)]) if meta.get("fields", {"fieldname": "enabled", "fieldtype": "Check"}): filters.append([doctype, "enabled", "=", 1]) if meta.get("fields", {"fieldname": "disabled", "fieldtype": "Check"}): filters.append([doctype, "disabled", "!=", 1]) # format a list of fields combining search fields and filter fields fields = get_std_fields_list(meta, searchfield or "name") if filter_fields: fields = list(set(fields + json.loads(filter_fields))) formatted_fields = ["`tab%s`.`%s`" % (meta.name, f.strip()) for f in fields] # find relevance as location of search term from the beginning of string `name`. used for sorting results. formatted_fields.append( """locate({_txt}, `tab{doctype}`.`name`) as `_relevance`""".format( _txt=frappe.db.escape((txt or "").replace("%", "").replace("@", "")), doctype=doctype ) ) # In order_by, `idx` gets second priority, because it stores link count from frappe.model.db_query import get_order_by order_by_based_on_meta = get_order_by(doctype, meta) # 2 is the index of _relevance column order_by = "_relevance, {0}, `tab{1}`.idx desc".format(order_by_based_on_meta, doctype) ptype = "select" if frappe.only_has_select_perm(doctype) else "read" ignore_permissions = ( True if doctype == "DocType" else (cint(ignore_user_permissions) and has_permission(doctype, ptype=ptype)) ) if doctype in translated_search_doctypes: page_length = None values = frappe.get_list( doctype, filters=filters, fields=formatted_fields, or_filters=or_filters, limit_start=start, limit_page_length=page_length, order_by=order_by, ignore_permissions=ignore_permissions, reference_doctype=reference_doctype, as_list=not as_dict, strict=False, ) if doctype in translated_search_doctypes: # Filtering the values array so that query is included in very element values = ( v for v in values if re.search(f"{re.escape(txt)}.*", _(v.name if as_dict else v[0]), re.IGNORECASE) ) # Sorting the values array so that relevant results always come first # This will first bring elements on top in which query is a prefix of element # Then it will bring the rest of the elements and sort them in lexicographical order values = sorted(values, key=lambda x: relevance_sorter(x, txt, as_dict)) # remove _relevance from results if as_dict: for r in values: r.pop("_relevance") frappe.response["values"] = values else: frappe.response["values"] = [r[:-1] for r in values]