Role and User Permissions

This commit is contained in:
Anand Doshi
2014-05-28 18:49:13 +05:30
parent 69eec9e344
commit 4985691617
10 changed files with 116 additions and 385 deletions

View File

@@ -48,6 +48,7 @@ doc_events = {
"on_cancel": "erpnext.stock.doctype.material_request.material_request.update_completed_qty" "on_cancel": "erpnext.stock.doctype.material_request.material_request.update_completed_qty"
}, },
"User": { "User": {
"validate": "erpnext.hr.doctype.employee.employee.validate_employee_role",
"on_update": "erpnext.hr.doctype.employee.employee.update_user_permissions" "on_update": "erpnext.hr.doctype.employee.employee.update_user_permissions"
} }
} }

View File

@@ -55,7 +55,7 @@ class Employee(Document):
frappe.permissions.set_user_permission_if_allowed("Company", self.company, self.user_id) frappe.permissions.set_user_permission_if_allowed("Company", self.company, self.user_id)
def update_leave_approver_user_permissions(self): def update_leave_approver_user_permissions(self):
"""restrict to this employee for leave approver""" """add employee user permission for leave approver"""
employee_leave_approvers = [d.leave_approver for d in self.get("employee_leave_approvers")] employee_leave_approvers = [d.leave_approver for d in self.get("employee_leave_approvers")]
if self.reports_to and self.reports_to not in employee_leave_approvers: if self.reports_to and self.reports_to not in employee_leave_approvers:
employee_leave_approvers.append(frappe.db.get_value("Employee", self.reports_to, "user_id")) employee_leave_approvers.append(frappe.db.get_value("Employee", self.reports_to, "user_id"))
@@ -204,13 +204,15 @@ def make_salary_structure(source_name, target=None):
target.make_earn_ded_table() target.make_earn_ded_table()
return target return target
def update_user_permissions(doc, method): def validate_employee_role(doc, method):
# called via User hook # called via User hook
if "Employee" in [d.role for d in doc.get("user_roles")]: if "Employee" in [d.role for d in doc.get("user_roles")]:
try: if not frappe.db.get_value("Employee", {"user_id": doc.name}):
employee = frappe.get_doc("Employee", {"user_id": doc.name})
employee.update_user_permissions()
except frappe.DoesNotExistError:
frappe.msgprint("Please set User ID field in an Employee record to set Employee Role") frappe.msgprint("Please set User ID field in an Employee record to set Employee Role")
doc.get("user_roles").remove(doc.get("user_roles", {"role": "Employee"})[0]) doc.get("user_roles").remove(doc.get("user_roles", {"role": "Employee"})[0])
def update_user_permissions(doc, method):
# called via User hook
if "Employee" in [d.role for d in doc.get("user_roles")]:
employee = frappe.get_doc("Employee", {"user_id": doc.name})
employee.update_user_permissions()

View File

@@ -2,10 +2,10 @@ execute:import unidecode # new requirement
erpnext.patches.v4_0.validate_v3_patch erpnext.patches.v4_0.validate_v3_patch
erpnext.patches.v4_0.fix_employee_user_id erpnext.patches.v4_0.fix_employee_user_id
erpnext.patches.v4_0.remove_employee_role_if_no_employee
erpnext.patches.v4_0.update_user_properties erpnext.patches.v4_0.update_user_properties
erpnext.patches.v4_0.apply_user_permissions
erpnext.patches.v4_0.move_warehouse_user_to_restrictions erpnext.patches.v4_0.move_warehouse_user_to_restrictions
execute:frappe.delete_doc_if_exists("DocType", "Warehouse User")
erpnext.patches.v4_0.new_permissions
erpnext.patches.v4_0.global_defaults_to_system_settings erpnext.patches.v4_0.global_defaults_to_system_settings
erpnext.patches.v4_0.update_incharge_name_to_sales_person_in_maintenance_schedule erpnext.patches.v4_0.update_incharge_name_to_sales_person_in_maintenance_schedule
execute:frappe.reload_doc('accounts', 'doctype', 'sales_invoice') # 2014-01-29 execute:frappe.reload_doc('accounts', 'doctype', 'sales_invoice') # 2014-01-29

View File

@@ -0,0 +1,45 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
update_hr_permissions()
update_permissions()
remove_duplicate_user_permissions()
frappe.clear_cache()
def update_hr_permissions():
from frappe.core.page.user_permissions import user_permissions
# add set user permissions rights to HR Manager
frappe.db.sql("""update `tabDocPerm` set `set_user_permissions`=1 where parent in ('Employee', 'Leave Application')
and role='HR Manager' and permlevel=0 and `read`=1""")
# apply user permissions on Employee and Leave Application
frappe.db.sql("""update `tabDocPerm` set `apply_user_permissions`=1 where parent in ('Employee', 'Leave Application')
and role in ('Employee', 'Leave Approver') and permlevel=0 and `read`=1""")
frappe.clear_cache()
# save employees to run on_update events
for employee in frappe.db.sql_list("""select name from `tabEmployee`"""):
frappe.get_doc("Employee", employee).save()
def update_permissions():
# clear match conditions other than owner
frappe.db.sql("""update tabDocPerm set `match`=''
where ifnull(`match`,'') not in ('', 'owner')""")
def remove_duplicate_user_permissions():
# remove duplicate user_permissions (if they exist)
for d in frappe.db.sql("""select parent, defkey, defvalue,
count(*) as cnt from tabDefaultValue
where parent not in ('__global', '__default')
group by parent, defkey, defvalue""", as_dict=1):
if d.cnt > 1:
# order by parenttype so that user permission does not get removed!
frappe.db.sql("""delete from tabDefaultValue where `parent`=%s and `defkey`=%s and
`defvalue`=%s order by parenttype limit %s""", (d.parent, d.defkey, d.defvalue, d.cnt-1))

View File

@@ -3,11 +3,11 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe import frappe
import frappe.permissions
def execute(): def execute():
from frappe.core.page.user_permissions import user_permissions
for warehouse, user in frappe.db.sql("""select parent, user from `tabWarehouse User`"""): for warehouse, user in frappe.db.sql("""select parent, user from `tabWarehouse User`"""):
user_permissions.add(user, "Warehouse", warehouse) frappe.permissions.add_user_permission("Warehouse", warehouse, user)
frappe.delete_doc("DocType", "Warehouse User") frappe.delete_doc_if_exists("DocType", "Warehouse User")
frappe.reload_doc("stock", "doctype", "warehouse") frappe.reload_doc("stock", "doctype", "warehouse")

View File

@@ -1,24 +0,0 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
# reset Page perms
from frappe.core.page.permission_manager.permission_manager import reset
reset("Page")
reset("Report")
# patch to move print, email into DocPerm
for doctype, hide_print, hide_email in frappe.db.sql("""select name, ifnull(allow_print, 0), ifnull(allow_email, 0)
from `tabDocType` where ifnull(issingle, 0)=0 and ifnull(istable, 0)=0 and
(ifnull(allow_print, 0)=0 or ifnull(allow_email, 0)=0)"""):
if not hide_print:
frappe.db.sql("""update `tabDocPerm` set `print`=1
where permlevel=0 and `read`=1 and parent=%s""", doctype)
if not hide_email:
frappe.db.sql("""update `tabDocPerm` set `email`=1
where permlevel=0 and `read`=1 and parent=%s""", doctype)

View File

@@ -0,0 +1,15 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
import frappe.permissions
def execute():
for user in frappe.db.sql_list("select distinct parent from `tabUserRole` where role='Employee'"):
# if employee record does not exists, remove employee role!
if not frappe.db.get_value("Employee", {"user_id": user}):
user = frappe.get_doc("User", user)
for role in user.get("user_roles", {"role": "Employee"}):
user.get("user_roles").remove(role)
user.save()

View File

@@ -7,100 +7,45 @@ import frappe.permissions
import frappe.defaults import frappe.defaults
def execute(): def execute():
frappe.reload_doc("core", "doctype", "docperm") frappe.reload_doc("core", "doctype", "docfield")
frappe.reload_doc("hr", "doctype", "employee") frappe.reload_doc("hr", "doctype", "employee")
update_user_permissions()
update_user_match() set_print_email_permissions()
add_employee_user_permissions_to_leave_approver() migrate_user_properties_to_user_permissions()
update_permissions()
remove_duplicate_user_permissions()
frappe.defaults.clear_cache()
frappe.clear_cache() frappe.clear_cache()
def update_user_permissions(): def migrate_user_properties_to_user_permissions():
frappe.reload_doc("core", "doctype", "docfield")
for d in frappe.db.sql("""select parent, defkey, defvalue from tabDefaultValue for d in frappe.db.sql("""select parent, defkey, defvalue from tabDefaultValue
where parent not in ('__global', '__default')""", as_dict=True): where parent not in ('__global', '__default')""", as_dict=True):
df = frappe.db.sql("""select options from tabDocField df = frappe.db.sql("""select options from tabDocField
where fieldname=%s and fieldtype='Link'""", d.defkey, as_dict=True) where fieldname=%s and fieldtype='Link'""", d.defkey, as_dict=True)
if df: if df:
frappe.db.sql("""update tabDefaultValue frappe.db.sql("""update tabDefaultValue
set defkey=%s, parenttype='User Permission' set defkey=%s, parenttype='User Permission'
where defkey=%s and where defkey=%s and
parent not in ('__global', '__default')""", (df[0].options, d.defkey)) parent not in ('__global', '__default')""", (df[0].options, d.defkey))
def update_user_match(): def set_print_email_permissions():
import frappe.defaults # reset Page perms
doctype_matches = {} from frappe.core.page.permission_manager.permission_manager import reset
for doctype, match in frappe.db.sql("""select parent, `match` from `tabDocPerm` reset("Page")
where `match` like %s and ifnull(`match`, '')!="leave_approver:user" """, "%:user"): reset("Report")
doctype_matches.setdefault(doctype, []).append(match)
for doctype, user_matches in doctype_matches.items():
meta = frappe.get_meta(doctype)
# for each user with roles of this doctype, check if match condition applies
for user in frappe.db.sql_list("""select name from `tabUser`
where enabled=1 and user_type='System User'"""):
user_roles = frappe.get_roles(user)
perms = meta.get({"doctype": "DocPerm", "permlevel": 0,
"role": ["in", [["All"] + user_roles]], "read": 1})
# user does not have required roles if "allow_print" not in frappe.db.get_table_columns("DocType"):
if not perms: return
continue
# assume match
user_match = True
for perm in perms:
if not perm.match:
# aha! non match found
user_match = False
break
if not user_match:
continue
# if match condition applies, restrict that user
# add that doc's restriction to that user
for match in user_matches:
for name in frappe.db.sql_list("""select name from `tab{doctype}`
where `{field}`=%s""".format(doctype=doctype, field=match.split(":")[0]), user):
frappe.defaults.add_default(doctype, name, user, "User Permission")
def add_employee_user_permissions_to_leave_approver():
from frappe.core.page.user_permissions import user_permissions
# add restrict rights to HR User and HR Manager
frappe.db.sql("""update `tabDocPerm` set `restrict`=1 where parent in ('Employee', 'Leave Application')
and role in ('HR User', 'HR Manager') and permlevel=0 and `read`=1""")
frappe.clear_cache()
# add Employee user_permissions (in on_update method)
for employee in frappe.db.sql_list("""select name from `tabEmployee`
where (exists(select leave_approver from `tabEmployee Leave Approver`
where `tabEmployee Leave Approver`.parent=`tabEmployee`.name)
or ifnull(`reports_to`, '')!='') and docstatus<2 and status='Active'"""):
frappe.get_doc("Employee", employee).save()
def update_permissions(): # patch to move print, email into DocPerm
# clear match conditions other than owner # NOTE: allow_print and allow_email are misnamed. They were used to hide print / hide email
frappe.db.sql("""update tabDocPerm set `match`='' for doctype, hide_print, hide_email in frappe.db.sql("""select name, ifnull(allow_print, 0), ifnull(allow_email, 0)
where ifnull(`match`,'') not in ('', 'owner')""") from `tabDocType` where ifnull(issingle, 0)=0 and ifnull(istable, 0)=0 and
(ifnull(allow_print, 0)=0 or ifnull(allow_email, 0)=0)"""):
def remove_duplicate_user_permissions(): if not hide_print:
# remove duplicate user_permissions (if they exist) frappe.db.sql("""update `tabDocPerm` set `print`=1
for d in frappe.db.sql("""select parent, defkey, defvalue, where permlevel=0 and `read`=1 and parent=%s""", doctype)
count(*) as cnt from tabDefaultValue
where parent not in ('__global', '__default') if not hide_email:
group by parent, defkey, defvalue""", as_dict=1): frappe.db.sql("""update `tabDocPerm` set `email`=1
if d.cnt > 1: where permlevel=0 and `read`=1 and parent=%s""", doctype)
# order by parenttype so that restriction does not get removed!
frappe.db.sql("""delete from tabDefaultValue where `parent`=%s and `defkey`=%s and
`defvalue`=%s order by parenttype limit %s""", (d.parent, d.defkey, d.defvalue, d.cnt-1))

View File

@@ -1,355 +1,102 @@
{ {
"_last_update": null,
"_user_tags": null,
"allow_attach": null,
"allow_copy": null,
"allow_email": null,
"allow_import": null,
"allow_print": null,
"allow_rename": null,
"allow_trash": null,
"autoname": null,
"change_log": null,
"client_script": null,
"client_script_core": null,
"client_string": null,
"colour": null,
"creation": "2013-06-25 10:25:16", "creation": "2013-06-25 10:25:16",
"custom": null,
"default_print_format": null,
"description": "Settings for Selling Module", "description": "Settings for Selling Module",
"docstatus": 0, "docstatus": 0,
"doctype": "DocType", "doctype": "DocType",
"document_type": "Other", "document_type": "Other",
"dt_template": null,
"fields": [ "fields": [
{ {
"allow_on_submit": null,
"default": "Customer Name", "default": "Customer Name",
"depends_on": null,
"description": null,
"fieldname": "cust_master_name", "fieldname": "cust_master_name",
"fieldtype": "Select", "fieldtype": "Select",
"hidden": null,
"in_filter": null,
"in_list_view": 1, "in_list_view": 1,
"label": "Customer Naming By", "label": "Customer Naming By",
"no_column": null,
"no_copy": null,
"oldfieldname": null,
"oldfieldtype": null,
"options": "Customer Name\nNaming Series", "options": "Customer Name\nNaming Series",
"permlevel": 0, "permlevel": 0
"print_hide": null,
"print_width": null,
"read_only": null,
"report_hide": null,
"reqd": null,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
}, },
{ {
"allow_on_submit": null,
"default": null,
"depends_on": null,
"description": null,
"fieldname": "campaign_naming_by", "fieldname": "campaign_naming_by",
"fieldtype": "Select", "fieldtype": "Select",
"hidden": null,
"in_filter": null,
"in_list_view": 1, "in_list_view": 1,
"label": "Campaign Naming By", "label": "Campaign Naming By",
"no_column": null,
"no_copy": null,
"oldfieldname": null,
"oldfieldtype": null,
"options": "Campaign Name\nNaming Series", "options": "Campaign Name\nNaming Series",
"permlevel": 0, "permlevel": 0
"print_hide": null,
"print_width": null,
"read_only": null,
"report_hide": null,
"reqd": null,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
}, },
{ {
"allow_on_submit": null,
"default": null,
"depends_on": null,
"description": "<a href=\"#Sales Browser/Customer Group\">Add / Edit</a>", "description": "<a href=\"#Sales Browser/Customer Group\">Add / Edit</a>",
"fieldname": "customer_group", "fieldname": "customer_group",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": null,
"in_filter": null,
"in_list_view": 1, "in_list_view": 1,
"label": "Default Customer Group", "label": "Default Customer Group",
"no_column": null,
"no_copy": null,
"oldfieldname": null,
"oldfieldtype": null,
"options": "Customer Group", "options": "Customer Group",
"permlevel": 0, "permlevel": 0
"print_hide": null,
"print_width": null,
"read_only": null,
"report_hide": null,
"reqd": null,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
}, },
{ {
"allow_on_submit": null,
"default": null,
"depends_on": null,
"description": "<a href=\"#Sales Browser/Territory\">Add / Edit</a>", "description": "<a href=\"#Sales Browser/Territory\">Add / Edit</a>",
"fieldname": "territory", "fieldname": "territory",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": null,
"in_filter": null,
"in_list_view": 1, "in_list_view": 1,
"label": "Default Territory", "label": "Default Territory",
"no_column": null,
"no_copy": null,
"oldfieldname": null,
"oldfieldtype": null,
"options": "Territory", "options": "Territory",
"permlevel": 0, "permlevel": 0
"print_hide": null,
"print_width": null,
"read_only": null,
"report_hide": null,
"reqd": null,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
}, },
{ {
"allow_on_submit": null,
"default": null,
"depends_on": null,
"description": null,
"fieldname": "selling_price_list", "fieldname": "selling_price_list",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": null,
"in_filter": null,
"in_list_view": 1, "in_list_view": 1,
"label": "Default Price List", "label": "Default Price List",
"no_column": null,
"no_copy": null,
"oldfieldname": null,
"oldfieldtype": null,
"options": "Price List", "options": "Price List",
"permlevel": 0, "permlevel": 0
"print_hide": null,
"print_width": null,
"read_only": null,
"report_hide": null,
"reqd": null,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
}, },
{ {
"allow_on_submit": null,
"default": null,
"depends_on": null,
"description": null,
"fieldname": "column_break_5", "fieldname": "column_break_5",
"fieldtype": "Column Break", "fieldtype": "Column Break",
"hidden": null, "permlevel": 0
"in_filter": null,
"in_list_view": null,
"label": null,
"no_column": null,
"no_copy": null,
"oldfieldname": null,
"oldfieldtype": null,
"options": null,
"permlevel": 0,
"print_hide": null,
"print_width": null,
"read_only": null,
"report_hide": null,
"reqd": null,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
}, },
{ {
"allow_on_submit": null,
"default": null,
"depends_on": null,
"description": null,
"fieldname": "so_required", "fieldname": "so_required",
"fieldtype": "Select", "fieldtype": "Select",
"hidden": null,
"in_filter": null,
"in_list_view": null,
"label": "Sales Order Required", "label": "Sales Order Required",
"no_column": null,
"no_copy": null,
"oldfieldname": null,
"oldfieldtype": null,
"options": "No\nYes", "options": "No\nYes",
"permlevel": 0, "permlevel": 0
"print_hide": null,
"print_width": null,
"read_only": null,
"report_hide": null,
"reqd": null,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
}, },
{ {
"allow_on_submit": null,
"default": null,
"depends_on": null,
"description": null,
"fieldname": "dn_required", "fieldname": "dn_required",
"fieldtype": "Select", "fieldtype": "Select",
"hidden": null,
"in_filter": null,
"in_list_view": null,
"label": "Delivery Note Required", "label": "Delivery Note Required",
"no_column": null,
"no_copy": null,
"oldfieldname": null,
"oldfieldtype": null,
"options": "No\nYes", "options": "No\nYes",
"permlevel": 0, "permlevel": 0
"print_hide": null,
"print_width": null,
"read_only": null,
"report_hide": null,
"reqd": null,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
}, },
{ {
"allow_on_submit": null,
"default": null,
"depends_on": null,
"description": null,
"fieldname": "maintain_same_sales_rate", "fieldname": "maintain_same_sales_rate",
"fieldtype": "Check", "fieldtype": "Check",
"hidden": null,
"in_filter": null,
"in_list_view": null,
"label": "Maintain Same Rate Throughout Sales Cycle", "label": "Maintain Same Rate Throughout Sales Cycle",
"no_column": null, "permlevel": 0
"no_copy": null,
"oldfieldname": null,
"oldfieldtype": null,
"options": null,
"permlevel": 0,
"print_hide": null,
"print_width": null,
"read_only": null,
"report_hide": null,
"reqd": null,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
}, },
{ {
"allow_on_submit": null,
"default": null,
"depends_on": null,
"description": null,
"fieldname": "editable_price_list_rate", "fieldname": "editable_price_list_rate",
"fieldtype": "Check", "fieldtype": "Check",
"hidden": null,
"in_filter": null,
"in_list_view": null,
"label": "Allow user to edit Price List Rate in transactions", "label": "Allow user to edit Price List Rate in transactions",
"no_column": null, "permlevel": 0
"no_copy": null,
"oldfieldname": null,
"oldfieldtype": null,
"options": null,
"permlevel": 0,
"print_hide": null,
"print_width": null,
"read_only": null,
"report_hide": null,
"reqd": null,
"search_index": null,
"set_only_once": null,
"trigger": null,
"width": null
} }
], ],
"hide_heading": null,
"hide_toolbar": null,
"icon": "icon-cog", "icon": "icon-cog",
"idx": 1, "idx": 1,
"in_create": null,
"in_dialog": null,
"is_submittable": null,
"is_transaction_doc": null,
"issingle": 1, "issingle": 1,
"istable": null, "modified": "2014-05-28 18:12:55.898953",
"max_attachments": null,
"menu_index": null,
"modified": "2014-04-16 12:21:36.117261",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Selling", "module": "Selling",
"name": "Selling Settings", "name": "Selling Settings",
"name_case": null,
"owner": "Administrator", "owner": "Administrator",
"parent": null,
"parent_node": null,
"parentfield": null,
"parenttype": null,
"permissions": [ "permissions": [
{ {
"amend": null,
"cancel": null,
"create": 1, "create": 1,
"delete": null,
"email": 1, "email": 1,
"export": null,
"import": null,
"match": null,
"permlevel": 0, "permlevel": 0,
"print": 1, "print": 1,
"read": 1, "read": 1,
"report": null,
"restrict": null,
"role": "System Manager", "role": "System Manager",
"submit": null,
"write": 1 "write": 1
} }
], ]
"plugin": null,
"print_outline": null,
"read_only": null,
"read_only_onload": null,
"search_fields": null,
"server_code": null,
"server_code_compiled": null,
"server_code_core": null,
"server_code_error": null,
"show_in_menu": null,
"smallicon": null,
"subject": null,
"tag_fields": null,
"title_field": null,
"use_template": null,
"version": null
} }

View File

@@ -392,7 +392,7 @@ def create_logo(args):
def add_all_roles_to(name): def add_all_roles_to(name):
user = frappe.get_doc("User", name) user = frappe.get_doc("User", name)
for role in frappe.db.sql("""select name from tabRole"""): for role in frappe.db.sql("""select name from tabRole"""):
if role[0] not in ["Administrator", "Guest", "All", "Customer", "Supplier", "Partner"]: if role[0] not in ["Administrator", "Guest", "All", "Customer", "Supplier", "Partner", "Employee"]:
d = user.append("user_roles") d = user.append("user_roles")
d.role = role[0] d.role = role[0]
user.save() user.save()