From 2926651e1ca7d324f5a9e0b72b28b5e9e3137130 Mon Sep 17 00:00:00 2001 From: Anand Doshi Date: Mon, 23 Dec 2013 19:59:29 +0530 Subject: [PATCH] Restrict Employee and Leave Approver to relevant Employee and Leave Application records --- hr/doctype/employee/employee.py | 53 ++++++++------- hr/doctype/employee/employee.txt | 4 +- .../leave_application/leave_application.txt | 3 +- patches/1312/p02_update_user_properties.py | 67 +++++++++++++------ 4 files changed, 78 insertions(+), 49 deletions(-) diff --git a/hr/doctype/employee/employee.py b/hr/doctype/employee/employee.py index 46f46da80f..6684951a93 100644 --- a/hr/doctype/employee/employee.py +++ b/hr/doctype/employee/employee.py @@ -7,13 +7,11 @@ import webnotes from webnotes.utils import getdate, validate_email_add, cstr, cint from webnotes.model.doc import make_autoname from webnotes import msgprint, _ +import webnotes.permissions +from webnotes.defaults import get_restrictions +from webnotes.model.controller import DocListController - -class DocType: - def __init__(self,doc,doclist=[]): - self.doc = doc - self.doclist = doclist - +class DocType(DocListController): def autoname(self): naming_method = webnotes.conn.get_value("HR Settings", None, "emp_created_by") if not naming_method: @@ -39,33 +37,36 @@ class DocType: def on_update(self): if self.doc.user_id: + self.restrict_user() self.update_user_default() self.update_profile() + + self.restrict_leave_approver() - def update_user_default(self): - from webnotes.defaults import get_restrictions - if not "HR User" in webnotes.local.user.get_roles(): - if not self.doc.user_id in get_restrictions().get("Employee", []): - webnotes.conn.set_default("Employee", self.doc.name, self.doc.user_id, "Restriction") + def restrict_user(self): + """restrict to this employee for user""" + self.add_restriction_if_required("Employee", self.doc.user_id) - webnotes.conn.set_default("employee", self.doc.name, self.doc.user_id) + def update_user_default(self): webnotes.conn.set_default("employee_name", self.doc.employee_name, self.doc.user_id) webnotes.conn.set_default("company", self.doc.company, self.doc.user_id) - self.set_default_leave_approver() - def set_default_leave_approver(self): - employee_leave_approvers = self.doclist.get({"parentfield": "employee_leave_approvers"}) - - if len(employee_leave_approvers): - webnotes.conn.set_default("leave_approver", employee_leave_approvers[0].leave_approver, - self.doc.user_id) - - elif self.doc.reports_to: - from webnotes.profile import Profile - reports_to_user = webnotes.conn.get_value("Employee", self.doc.reports_to, "user_id") - if "Leave Approver" in Profile(reports_to_user).get_roles(): - webnotes.conn.set_default("leave_approver", reports_to_user, self.doc.user_id) - + def restrict_leave_approver(self): + """restrict to this employee for leave approver""" + employee_leave_approvers = [d.leave_approver for d in self.doclist.get({"parentfield": "employee_leave_approvers"})] + if self.doc.reports_to and self.doc.reports_to not in employee_leave_approvers: + employee_leave_approvers.append(webnotes.conn.get_value("Employee", self.doc.reports_to, "user_id")) + + for user in employee_leave_approvers: + self.add_restriction_if_required("Employee", user) + self.add_restriction_if_required("Leave Application", user) + + def add_restriction_if_required(self, doctype, user): + if webnotes.permissions.has_only_non_restrict_role(webnotes.get_doctype(doctype), user) \ + and self.doc.name not in get_restrictions(user).get("Employee", []): + + webnotes.defaults.add_default("Employee", self.doc.name, user, "Restriction") + def update_profile(self): # add employee role if missing if not "Employee" in webnotes.conn.sql_list("""select role from tabUserRole diff --git a/hr/doctype/employee/employee.txt b/hr/doctype/employee/employee.txt index 225b4850c2..f8b08e08d4 100644 --- a/hr/doctype/employee/employee.txt +++ b/hr/doctype/employee/employee.txt @@ -2,7 +2,7 @@ { "creation": "2013-03-07 09:04:18", "docstatus": 0, - "modified": "2013-12-20 19:24:06", + "modified": "2013-12-23 19:35:27", "modified_by": "Administrator", "owner": "Administrator" }, @@ -760,6 +760,7 @@ "cancel": 1, "create": 1, "doctype": "DocPerm", + "restrict": 0, "role": "HR User", "write": 1 }, @@ -767,6 +768,7 @@ "cancel": 1, "create": 1, "doctype": "DocPerm", + "restrict": 1, "role": "HR Manager", "write": 1 } diff --git a/hr/doctype/leave_application/leave_application.txt b/hr/doctype/leave_application/leave_application.txt index 10c0429077..24de6a82fc 100644 --- a/hr/doctype/leave_application/leave_application.txt +++ b/hr/doctype/leave_application/leave_application.txt @@ -2,7 +2,7 @@ { "creation": "2013-02-20 11:18:11", "docstatus": 0, - "modified": "2013-12-20 19:24:12", + "modified": "2013-12-23 19:53:41", "modified_by": "Administrator", "owner": "Administrator" }, @@ -256,6 +256,7 @@ "permlevel": 0, "print": 1, "report": 1, + "restrict": 1, "role": "HR User", "submit": 1, "write": 1 diff --git a/patches/1312/p02_update_user_properties.py b/patches/1312/p02_update_user_properties.py index 4ac1ab9615..70c500f277 100644 --- a/patches/1312/p02_update_user_properties.py +++ b/patches/1312/p02_update_user_properties.py @@ -3,51 +3,59 @@ from __future__ import unicode_literals import webnotes +import webnotes.permissions +import webnotes.model.doctype +import webnotes.defaults def execute(): + webnotes.reload_doc("core", "doctype", "docperm") update_user_properties() update_user_match() + add_employee_restrictions_to_leave_approver() update_permissions() remove_duplicate_restrictions() + webnotes.defaults.clear_cache() webnotes.clear_cache() def update_user_properties(): webnotes.reload_doc("core", "doctype", "docfield") - for d in webnotes.conn.sql("""select parent, defkey, defvalue from tabDefaultValue + for d in webnotes.conn.sql("""select parent, defkey, defvalue from tabDefaultValue where parent not in ('__global', 'Control Panel')""", as_dict=True): - df = webnotes.conn.sql("""select options from tabDocField + df = webnotes.conn.sql("""select options from tabDocField where fieldname=%s and fieldtype='Link'""", d.defkey, as_dict=True) if df: - webnotes.conn.sql("""update tabDefaultValue - set defkey=%s, parenttype='Restriction' - where defkey=%s and + webnotes.conn.sql("""update tabDefaultValue + set defkey=%s, parenttype='Restriction' + where defkey=%s and parent not in ('__global', 'Control Panel')""", (df[0].options, d.defkey)) - + def update_user_match(): import webnotes.defaults doctype_matches = {} for doctype, match in webnotes.conn.sql("""select parent, `match` from `tabDocPerm` - where `match` like %s""", "%:user"): + where `match` like %s and ifnull(`match`, '')!="leave_approver:user" """, "%:user"): doctype_matches.setdefault(doctype, []).append(match) for doctype, user_matches in doctype_matches.items(): - # get permissions of this doctype - perms = webnotes.conn.sql("""select role, `match` from `tabDocPerm` - where parent=%s and permlevel=0 and `read`=1""", doctype, as_dict=True) + meta = webnotes.get_doctype(doctype) # for each user with roles of this doctype, check if match condition applies for profile in webnotes.conn.sql_list("""select name from `tabProfile` where enabled=1 and user_type='System User'"""): - roles = webnotes.get_roles(profile) + perms = webnotes.permissions.get_user_perms(meta, "read", profile) + # user does not have required roles + if not perms: + continue - user_match = False + # assume match + user_match = True for perm in perms: - if perm.role in roles and (perm.match and \ - (perm.match.endswith(":user") or perm.match.endswith(":profile"))): - user_match = True + if not perm.match: + # aha! non match found + user_match = False break if not user_match: @@ -60,18 +68,35 @@ def update_user_match(): where `{field}`=%s""".format(doctype=doctype, field=match.split(":")[0]), profile): webnotes.defaults.add_default(doctype, name, profile, "Restriction") + +def add_employee_restrictions_to_leave_approver(): + from core.page.user_properties import user_properties + + # add restrict rights to HR User and HR Manager + webnotes.conn.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""") + webnotes.model.doctype.clear_cache() + + # add Employee restrictions (in on_update method) + for employee in webnotes.conn.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`, '')!=''"""): + + webnotes.bean("Employee", employee).save() def update_permissions(): # clear match conditions other than owner webnotes.conn.sql("""update tabDocPerm set `match`='' where ifnull(`match`,'') not in ('', 'owner')""") - + def remove_duplicate_restrictions(): # remove duplicate restrictions (if they exist) - for d in webnotes.conn.sql("""select parent, defkey, defvalue, - count(*) as cnt from tabDefaultValue - where parent not in ('__global', 'Control Panel') + for d in webnotes.conn.sql("""select parent, defkey, defvalue, + count(*) as cnt from tabDefaultValue + where parent not in ('__global', 'Control Panel') group by parent, defkey, defvalue""", as_dict=1): if d.cnt > 1: - webnotes.conn.sql("""delete from tabDefaultValue where parent=%s, defkey=%s, - defvalue=%s limit %s""", (d.parent, d.defkey, d.defvalue, d.cnt-1)) \ No newline at end of file + # order by parenttype so that restriction does not get removed! + webnotes.conn.sql("""delete from tabDefaultValue where parent=%s, defkey=%s, + defvalue=%s order by parenttype limit %s""", (d.parent, d.defkey, d.defvalue, d.cnt-1))