Added import, export, print, email and restrict permissions
This commit is contained in:
parent
3b004ad23e
commit
97ea7f91e2
19 changed files with 371 additions and 188 deletions
|
|
@ -2,7 +2,7 @@
|
|||
{
|
||||
"creation": "2013-02-22 01:27:33",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-07-22 17:01:58",
|
||||
"modified": "2013-12-17 12:29:13",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
|
|
@ -150,6 +150,36 @@
|
|||
"print_width": "32px",
|
||||
"width": "32px"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "export",
|
||||
"fieldtype": "Check",
|
||||
"label": "Export"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "import",
|
||||
"fieldtype": "Check",
|
||||
"label": "Import"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "print",
|
||||
"fieldtype": "Check",
|
||||
"label": "Print"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "email",
|
||||
"fieldtype": "Check",
|
||||
"label": "Email"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "restrict",
|
||||
"fieldtype": "Check",
|
||||
"label": "Restrict"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "match",
|
||||
|
|
|
|||
|
|
@ -229,9 +229,10 @@ def validate_permissions(permissions, for_remove=False):
|
|||
if doctype:
|
||||
issingle = cint(webnotes.conn.get_value("DocType", doctype, "issingle"))
|
||||
issubmittable = cint(webnotes.conn.get_value("DocType", doctype, "is_submittable"))
|
||||
isimportable = cint(webnotes.conn.get_value("DocType", doctype, "allow_import"))
|
||||
|
||||
def get_txt(d):
|
||||
return "For %s (level %s) in %s row %s:" % (d.role, d.permlevel, d.parent, d.idx)
|
||||
return "For %s (level %s) in %s, row #%s:" % (d.role, d.permlevel, d.parent, d.idx)
|
||||
|
||||
def check_atleast_one_set(d):
|
||||
if not d.read and not d.write and not d.submit and not d.cancel and not d.create:
|
||||
|
|
@ -269,10 +270,25 @@ def validate_permissions(permissions, for_remove=False):
|
|||
if d.amend and not d.write:
|
||||
webnotes.msgprint(get_txt(d) + " Cannot set Amend if Cancel is not set.",
|
||||
raise_exception=True)
|
||||
if (d.fields.get("import") or d.export) and not d.report:
|
||||
webnotes.msgprint(get_txt(d) + " Cannot set Import or Export permission if Report is not set.",
|
||||
raise_exception=True)
|
||||
|
||||
def remove_report_if_single(d):
|
||||
if d.report and issingle:
|
||||
webnotes.msgprint(doctype + " is a single DocType, permission of type Report is meaningless.")
|
||||
def remove_rights_for_single(d):
|
||||
if not issingle:
|
||||
return
|
||||
|
||||
if d.report:
|
||||
webnotes.msgprint("{doctype} {meaningless}".format(doctype=doctype,
|
||||
meaningless=_("is a single DocType, permission of type Report is meaningless.")))
|
||||
d.report = 0
|
||||
d.fields["import"] = 0
|
||||
d.fields["export"] = 0
|
||||
|
||||
if d.restrict:
|
||||
webnotes.msgprint("{doctype} {meaningless}".format(doctype=doctype,
|
||||
meaningless=_("is a single DocType, permission of type Restrict is meaningless.")))
|
||||
d.restrict = 0
|
||||
|
||||
def check_if_submittable(d):
|
||||
if d.submit and not issubmittable:
|
||||
|
|
@ -282,6 +298,11 @@ def validate_permissions(permissions, for_remove=False):
|
|||
webnotes.msgprint(doctype + " is not Submittable, cannot assign amend rights.",
|
||||
raise_exception=True)
|
||||
|
||||
def check_if_importable(d):
|
||||
if d.fields.get("import") and not isimportable:
|
||||
webnotes.throw("{doctype}: {not_importable}".format(doctype=doctype,
|
||||
not_importable=_("is not allowed to be imported, cannot assign import rights.")))
|
||||
|
||||
for d in permissions:
|
||||
if not d.permlevel:
|
||||
d.permlevel=0
|
||||
|
|
@ -290,8 +311,9 @@ def validate_permissions(permissions, for_remove=False):
|
|||
check_double(d)
|
||||
check_permission_dependency(d)
|
||||
check_if_submittable(d)
|
||||
check_if_importable(d)
|
||||
check_level_zero_is_set(d)
|
||||
remove_report_if_single(d)
|
||||
remove_rights_for_single(d)
|
||||
|
||||
def make_module_and_roles(doclist, perm_doctype="DocPerm"):
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
{
|
||||
"creation": "2013-02-18 13:36:19",
|
||||
"docstatus": 0,
|
||||
"modified": "2013-11-26 10:57:00",
|
||||
"modified": "2013-12-17 14:32:51",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
|
|
@ -321,28 +321,6 @@
|
|||
"reqd": 0,
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "allow_print",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"label": "Hide Print",
|
||||
"oldfieldname": "allow_print",
|
||||
"oldfieldtype": "Check",
|
||||
"reqd": 0,
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "allow_email",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"label": "Hide Email",
|
||||
"oldfieldname": "allow_email",
|
||||
"oldfieldtype": "Check",
|
||||
"reqd": 0,
|
||||
"search_index": 0
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "allow_copy",
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@ def get_doctype_options():
|
|||
|
||||
@webnotes.whitelist()
|
||||
def get_template(doctype=None, parent_doctype=None, all_doctypes="No", with_data="No"):
|
||||
webnotes.check_admin_or_system_manager()
|
||||
import webnotes.permissions
|
||||
webnotes.permissions.check_admin_or_system_manager()
|
||||
all_doctypes = all_doctypes=="Yes"
|
||||
if not parent_doctype:
|
||||
parent_doctype = doctype
|
||||
|
|
@ -217,8 +218,9 @@ def get_template(doctype=None, parent_doctype=None, all_doctypes="No", with_data
|
|||
@webnotes.whitelist()
|
||||
def upload(rows = None, submit_after_import=None, ignore_encoding_errors=False, overwrite=False, ignore_links=False):
|
||||
"""upload data"""
|
||||
import webnotes.permissions
|
||||
webnotes.flags.mute_emails = True
|
||||
webnotes.check_admin_or_system_manager()
|
||||
webnotes.permissions.check_admin_or_system_manager()
|
||||
# extra input params
|
||||
params = json.loads(webnotes.form_dict.get("params") or '{}')
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ wn.pages['permission-manager'].onload = function(wrapper) {
|
|||
<tr><td>\
|
||||
<h4><i class='icon-question-sign'></i> "+wn._("Quick Help for Setting Permissions")+":</h4>\
|
||||
<ol>\
|
||||
<li>"+wn._("Permissions are set on Roles and Document Types (called DocTypes) by restricting read, edit, make new, submit, cancel, amend and report rights.")+"</li>\
|
||||
<li>"+wn._("Permissions are set on Roles and Document Types (called DocTypes) by restricting read, edit, make new, submit, cancel, amend, report, import, export, print, email and restrict rights.")+"</li>\
|
||||
<li>"+wn._("Permissions translate to Users based on what Role they are assigned")+".</li>\
|
||||
<li>"+wn._("To set user roles, just go to <a href='#List/Profile'>Setup > Users</a> and click on the user to assign roles.")+"</li>\
|
||||
<li>"+wn._("The system provides pre-defined roles, but you can <a href='#List/Role'>add new roles</a> to set finer permissions")+".</li>\
|
||||
|
|
@ -45,8 +45,9 @@ wn.pages['permission-manager'].onload = function(wrapper) {
|
|||
</tr></td>\
|
||||
<tr><td>\
|
||||
<h4><i class='icon-cog'></i> "+wn._("Advanced Settings")+":</h4>\
|
||||
<p>"+wn._("To further restrict permissions based on certain values, like Company or Territory in a document, please go to <a href='#user-properties'>User Restrictions</a>")+" <br><br>"+
|
||||
"<p>"+wn._("Once you have set this, the users will only be able access documents where the link (e.g Company) exists.")+"</p><hr>\
|
||||
<p>"+wn._("To further restrict permissions based on certain values, like Company or Territory in a document, please go to <a href='#user-properties'>User Restrictions</a>")+"</p>"+
|
||||
"<p>"+wn._("Once you have set this, the users will only be able access documents where the link (e.g Company) exists.")+"</p>"+
|
||||
"<p>"+wn._("Apart from System Manager, roles with Restrict permission can restrict other users for that Document Type")+"</p><hr>\
|
||||
<p>"+wn._("If these instructions where not helpful, please add in your suggestions at <a href='https://github.com/webnotes/wnframework/issues'>GitHub Issues</a>")+"</p>\
|
||||
</tr></td>\
|
||||
</table>");
|
||||
|
|
@ -160,37 +161,42 @@ wn.PermissionEngine = Class.extend({
|
|||
},
|
||||
show_permission_table: function(perm_list) {
|
||||
var me = this;
|
||||
this.table = $("<table class='table table-bordered'>\
|
||||
<thead><tr></tr></thead>\
|
||||
<tbody></tbody>\
|
||||
</table>").appendTo(this.body);
|
||||
this.table = $("<div class='table-responsive'>\
|
||||
<table class='table table-bordered'>\
|
||||
<thead><tr></tr></thead>\
|
||||
<tbody></tbody>\
|
||||
</table>\
|
||||
</div>").appendTo(this.body);
|
||||
|
||||
$.each([["Document Type", 150], ["Role", 100], ["Level",50],
|
||||
["Read", 50], ["Edit", 50], ["Make New", 50],
|
||||
["Submit", 50], ["Cancel", 50], ["Amend", 50], ["Report", 50],
|
||||
["Condition", 150], ["", 50]], function(i, col) {
|
||||
$.each([["Document Type", 150], ["Role", 150], ["Level", 40],
|
||||
["Permissions", 270], ["Condition", 100], ["", 40]], function(i, col) {
|
||||
$("<th>").html(col[0]).css("width", col[1]+"px")
|
||||
.appendTo(me.table.find("thead tr"));
|
||||
});
|
||||
|
||||
var add_cell = function(row, d, fieldname, is_check) {
|
||||
var cell = $("<td>").appendTo(row).attr("data-fieldname", fieldname);
|
||||
if(is_check) {
|
||||
if(d.permlevel > 0 && ["read", "write"].indexOf(fieldname)==-1) {
|
||||
cell.html("-");
|
||||
} else {
|
||||
var input = $("<input type='checkbox'>")
|
||||
.prop("checked", d[fieldname] ? true: false)
|
||||
.attr("data-ptype", fieldname)
|
||||
.attr("data-name", d.name)
|
||||
.attr("data-doctype", d.parent)
|
||||
.appendTo(cell);
|
||||
}
|
||||
} else {
|
||||
cell.html(d[fieldname]);
|
||||
return $("<td>").appendTo(row)
|
||||
.attr("data-fieldname", fieldname)
|
||||
.html(d[fieldname]);
|
||||
};
|
||||
|
||||
var add_check = function(cell, d, fieldname) {
|
||||
if(d.permlevel > 0 && ["read", "write"].indexOf(fieldname)==-1) {
|
||||
return;
|
||||
}
|
||||
return cell;
|
||||
}
|
||||
|
||||
var checkbox = $("<div class='col-md-4'><div class='checkbox'>\
|
||||
<label><input type='checkbox'>"+fieldname+"</input></label>\
|
||||
</div></div>").appendTo(cell)
|
||||
.attr("data-fieldname", fieldname)
|
||||
.css("text-transform", "capitalize");
|
||||
|
||||
checkbox.find("input")
|
||||
.prop("checked", d[fieldname] ? true: false)
|
||||
.attr("data-ptype", fieldname)
|
||||
.attr("data-name", d.name)
|
||||
.attr("data-doctype", d.parent)
|
||||
};
|
||||
|
||||
$.each(perm_list, function(i, d) {
|
||||
if(!d.permlevel) d.permlevel = 0;
|
||||
|
|
@ -203,13 +209,21 @@ wn.PermissionEngine = Class.extend({
|
|||
cell.css("font-weight", "bold");
|
||||
row.addClass("warning");
|
||||
}
|
||||
add_cell(row, d, "read", true);
|
||||
add_cell(row, d, "write", true);
|
||||
add_cell(row, d, "create", true);
|
||||
add_cell(row, d, "submit", true);
|
||||
add_cell(row, d, "cancel", true);
|
||||
add_cell(row, d, "amend", true);
|
||||
add_cell(row, d, "report", true);
|
||||
|
||||
var perm_cell = add_cell(row, d, "permissions").css("padding-top", 0);
|
||||
var perm_container = $("<div class='row'></div>").appendTo(perm_cell);
|
||||
add_check(perm_container, d, "read");
|
||||
add_check(perm_container, d, "write");
|
||||
add_check(perm_container, d, "create");
|
||||
add_check(perm_container, d, "submit");
|
||||
add_check(perm_container, d, "cancel");
|
||||
add_check(perm_container, d, "amend");
|
||||
add_check(perm_container, d, "report");
|
||||
add_check(perm_container, d, "import");
|
||||
add_check(perm_container, d, "export");
|
||||
add_check(perm_container, d, "print");
|
||||
add_check(perm_container, d, "email");
|
||||
add_check(perm_container, d, "restrict");
|
||||
|
||||
// buttons
|
||||
me.add_match_button(row, d);
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ wn.UserProperties = Class.extend({
|
|||
});
|
||||
},
|
||||
get_link_names: function() {
|
||||
return $.map(this.options.link_fields, function(l) { return l[0]; });
|
||||
return this.options.link_fields;
|
||||
},
|
||||
set_from_route: function() {
|
||||
var me = this;
|
||||
|
|
|
|||
|
|
@ -4,30 +4,41 @@
|
|||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
import webnotes.defaults
|
||||
import webnotes.permissions
|
||||
|
||||
@webnotes.whitelist()
|
||||
def get_users_and_links():
|
||||
webnotes.only_for(("Restriction Manager", "System Manager"))
|
||||
return {
|
||||
"users": webnotes.conn.sql_list("""select name from tabProfile where
|
||||
ifnull(enabled,0)=1 and
|
||||
name not in ("Administrator", "Guest")"""),
|
||||
"link_fields": webnotes.conn.sql("""select name, name from tabDocType
|
||||
where ifnull(issingle,0)=0 and ifnull(istable,0)=0""")
|
||||
"link_fields": get_restrictable_doctypes()
|
||||
}
|
||||
|
||||
@webnotes.whitelist()
|
||||
def get_properties(parent=None, defkey=None, defvalue=None):
|
||||
webnotes.only_for(("Restriction Manager", "System Manager"))
|
||||
if defkey and not webnotes.permissions.can_restrict(defkey, defvalue):
|
||||
raise webnotes.PermissionError
|
||||
|
||||
conditions, values = _build_conditions(locals())
|
||||
|
||||
return webnotes.conn.sql("""select name, parent, defkey, defvalue
|
||||
properties = webnotes.conn.sql("""select name, parent, defkey, defvalue
|
||||
from tabDefaultValue
|
||||
where parent not in ('Control Panel', '__global')
|
||||
and substr(defkey,1,1)!='_'
|
||||
and parenttype='Restriction'
|
||||
{conditions}
|
||||
order by parent, defkey""".format(conditions=conditions), values, as_dict=True)
|
||||
|
||||
if not defkey:
|
||||
out = []
|
||||
doctypes = get_restrictable_doctypes()
|
||||
for p in properties:
|
||||
if p.defkey in doctypes:
|
||||
out.append(p)
|
||||
properties = out
|
||||
|
||||
return properties
|
||||
|
||||
def _build_conditions(filters):
|
||||
conditions = []
|
||||
|
|
@ -40,17 +51,34 @@ def _build_conditions(filters):
|
|||
return "\n".join(conditions), values
|
||||
|
||||
@webnotes.whitelist()
|
||||
def remove(user, name):
|
||||
webnotes.only_for(("Restriction Manager", "System Manager"))
|
||||
def remove(user, name, defkey, defvalue):
|
||||
if not webnotes.permissions.can_restrict_user(user, defkey, defvalue):
|
||||
raise webnotes.PermissionError
|
||||
|
||||
webnotes.defaults.clear_default(name=name)
|
||||
|
||||
@webnotes.whitelist()
|
||||
def add(user, defkey, defvalue):
|
||||
webnotes.only_for(("Restriction Manager", "System Manager"))
|
||||
if not webnotes.permissions.can_restrict_user(user, defkey, defvalue):
|
||||
raise webnotes.PermissionError
|
||||
|
||||
# check if already exists
|
||||
d = webnotes.conn.sql("""select name from tabDefaultValue
|
||||
where parent=%s and parenttype='Restriction' and defkey=%s and defvalue=%s""", (user, defkey, defvalue))
|
||||
|
||||
if not d:
|
||||
webnotes.defaults.add_default(defkey, defvalue, user, "Restriction")
|
||||
webnotes.defaults.add_default(defkey, defvalue, user, "Restriction")
|
||||
|
||||
def get_restrictable_doctypes():
|
||||
user_roles = webnotes.get_roles()
|
||||
condition = ""
|
||||
values = []
|
||||
if "System Manager" not in user_roles:
|
||||
condition = """and exists(select `tabDocPerm`.name from `tabDocPerm`
|
||||
where `tabDocPerm`.parent=`tabDocType`.name and restrict=1
|
||||
and `tabDocPerm`.name in ({roles}))""".format(roles=", ".join(["%s"]*len(user_roles)))
|
||||
values = user_roles
|
||||
|
||||
return webnotes.conn.sql_list("""select name from tabDocType
|
||||
where ifnull(issingle,0)=0 and ifnull(istable,0)=0 {condition}""".format(condition=condition),
|
||||
values)
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ wn.ui.form.InfoBar = Class.extend({
|
|||
function() { me.frm.toolbar.show_linked_with(); });
|
||||
|
||||
// link to user restrictions
|
||||
if(wn.user.can_restrict()) {
|
||||
if(wn.model.can_restrict(me.frm.doctype)) {
|
||||
this.$user_properties = this.appframe.add_icon_btn("2", "icon-shield",
|
||||
wn._("User Permission Restrictions"), function() {
|
||||
wn.route_options = {
|
||||
|
|
|
|||
|
|
@ -125,10 +125,6 @@ $.extend(wn.user, {
|
|||
is_report_manager: function() {
|
||||
return wn.user.has_role(['Administrator', 'System Manager', 'Report Manager']);
|
||||
},
|
||||
|
||||
can_restrict: function() {
|
||||
return wn.user.has_role(["Restriction Manager", "System Manager"]);
|
||||
},
|
||||
});
|
||||
|
||||
wn.session_alive = true;
|
||||
|
|
|
|||
|
|
@ -120,24 +120,24 @@ $.extend(wn.model, {
|
|||
},
|
||||
|
||||
can_create: function(doctype) {
|
||||
return wn.boot.profile.can_create.indexOf(doctype)!=-1;
|
||||
return wn.boot.profile.can_create.indexOf(doctype)!==-1;
|
||||
},
|
||||
|
||||
can_read: function(doctype) {
|
||||
return wn.boot.profile.can_read.indexOf(doctype)!=-1;
|
||||
return wn.boot.profile.can_read.indexOf(doctype)!==-1;
|
||||
},
|
||||
|
||||
can_write: function(doctype) {
|
||||
return wn.boot.profile.can_write.indexOf(doctype)!=-1;
|
||||
return wn.boot.profile.can_write.indexOf(doctype)!==-1;
|
||||
},
|
||||
|
||||
can_get_report: function(doctype) {
|
||||
return wn.boot.profile.can_get_report.indexOf(doctype)!=-1;
|
||||
return wn.boot.profile.can_get_report.indexOf(doctype)!==-1;
|
||||
},
|
||||
|
||||
can_delete: function(doctype) {
|
||||
if(!doctype) return false;
|
||||
return wn.boot.profile.can_cancel.indexOf(doctype)!=-1;
|
||||
return wn.boot.profile.can_cancel.indexOf(doctype)!==-1;
|
||||
},
|
||||
|
||||
is_submittable: function(doctype) {
|
||||
|
|
@ -145,6 +145,26 @@ $.extend(wn.model, {
|
|||
return locals.DocType[doctype] && locals.DocType[doctype].is_submittable;
|
||||
},
|
||||
|
||||
can_import: function(doctype) {
|
||||
return wn.boot.profile.can_import.indexOf(doctype)!==-1;
|
||||
},
|
||||
|
||||
can_export: function(doctype) {
|
||||
return wn.boot.profile.can_export.indexOf(doctype)!==-1;
|
||||
},
|
||||
|
||||
can_print: function(doctype) {
|
||||
return wn.boot.profile.can_print.indexOf(doctype)!==-1;
|
||||
},
|
||||
|
||||
can_email: function(doctype) {
|
||||
return wn.boot.profile.can_email.indexOf(doctype)!==-1;
|
||||
},
|
||||
|
||||
can_restrict: function(doctype) {
|
||||
return wn.boot.profile.can_restrict.indexOf(doctype)!==-1;
|
||||
},
|
||||
|
||||
has_value: function(dt, dn, fn) {
|
||||
// return true if property has value
|
||||
var val = locals[dt] && locals[dt][dn] && locals[dt][dn][fn];
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ wn.views.QueryReport = Class.extend({
|
|||
"icon-download");
|
||||
wn.utils.disable_export_btn(export_btn);
|
||||
|
||||
if(wn.user.can_restrict()) {
|
||||
if(wn.model.can_restrict("Report")) {
|
||||
this.appframe.add_primary_action(wn._("User Restrictions"), function() {
|
||||
wn.route_options = {
|
||||
property: "Report",
|
||||
|
|
|
|||
|
|
@ -514,7 +514,7 @@ wn.views.ReportView = wn.ui.Listing.extend({
|
|||
|
||||
make_user_restrictions: function() {
|
||||
var me = this;
|
||||
if(this.docname && wn.user.can_restrict()) {
|
||||
if(this.docname && wn.model.can_restrict("Report")) {
|
||||
this.page.appframe.add_button(wn._("User Permission Restrictions"), function() {
|
||||
wn.route_options = {
|
||||
property: "Report",
|
||||
|
|
|
|||
|
|
@ -327,86 +327,18 @@ def get_roles(username=None):
|
|||
return user.get_roles()
|
||||
else:
|
||||
return webnotes.profile.Profile(username).get_roles()
|
||||
|
||||
def check_admin_or_system_manager():
|
||||
if ("System Manager" not in get_roles()) and \
|
||||
(session.user!="Administrator"):
|
||||
msgprint("Only Allowed for Role System Manager or Administrator", raise_exception=True)
|
||||
|
||||
def has_permission(doctype, ptype="read", refdoc=None):
|
||||
"""check if user has permission"""
|
||||
if session.user=="Administrator" or conn.get_value("DocType", doctype, "istable")==1:
|
||||
return True
|
||||
import webnotes.permissions
|
||||
return webnotes.permissions.has_permission(doctype, ptype, refdoc)
|
||||
|
||||
meta = get_doctype(doctype)
|
||||
|
||||
# get user permissions
|
||||
perms = get_user_perms(meta, ptype)
|
||||
|
||||
if not perms:
|
||||
return False
|
||||
elif refdoc:
|
||||
if isinstance(refdoc, basestring):
|
||||
refdoc = doc(meta[0].name, refdoc)
|
||||
|
||||
if has_only_permitted_data(meta, refdoc) and has_match(perms, refdoc):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def get_user_perms(meta, ptype, user=None):
|
||||
from webnotes.utils import cint
|
||||
user_roles = get_roles(user)
|
||||
|
||||
return [p for p in meta.get({"doctype": "DocPerm"})
|
||||
if cint(p.get(ptype))==1 and cint(p.permlevel)==0 and (p.role=="All" or p.role in user_roles)]
|
||||
def clear_perms(doctype):
|
||||
conn.sql("""delete from tabDocPerm where parent=%s""", doctype)
|
||||
|
||||
def has_only_permitted_data(meta, refdoc):
|
||||
from webnotes.defaults import get_restrictions
|
||||
|
||||
has_restricted_data = False
|
||||
restrictions = get_restrictions()
|
||||
|
||||
if restrictions:
|
||||
fields_to_check = meta.get_restricted_fields(restrictions.keys())
|
||||
|
||||
if meta[0].name in restrictions:
|
||||
fields_to_check.append(_dict({"label":"Name", "fieldname":"name", "options": meta[0].name}))
|
||||
|
||||
for df in fields_to_check:
|
||||
if refdoc.get(df.fieldname) and refdoc.get(df.fieldname) not in restrictions[df.options]:
|
||||
msg = "{not_allowed}: {doctype} {having} {label} = {value}".format(
|
||||
not_allowed=_("Sorry, you are not allowed to access"), doctype=_(df.options),
|
||||
having=_("having"), label=_(df.label), value=refdoc.get(df.fieldname))
|
||||
|
||||
if refdoc.parentfield:
|
||||
msg = "{doctype}, {row} #{idx}, ".format(doctype=_(refdoc.doctype),
|
||||
row=_("Row"), idx=refdoc.idx) + msg
|
||||
|
||||
msgprint(msg)
|
||||
has_restricted_data = True
|
||||
|
||||
if has_restricted_data:
|
||||
# check all restrictions before returning
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def has_match(perms, refdoc):
|
||||
"""check owner match (if exists)"""
|
||||
for p in perms:
|
||||
if p.get("match")=="owner":
|
||||
if refdoc.get("owner")==local.session.user:
|
||||
# owner matches :)
|
||||
return True
|
||||
else:
|
||||
# found a permission without owner match :)
|
||||
return True
|
||||
|
||||
# no match :(
|
||||
return False
|
||||
def reset_perms(doctype):
|
||||
clear_perms(doctype)
|
||||
reload_doc(conn.get_value("DocType", doctype, "module"),
|
||||
"DocType", doctype, force=True)
|
||||
|
||||
def generate_hash():
|
||||
"""Generates random hash for session id"""
|
||||
|
|
@ -472,13 +404,6 @@ def delete_doc(doctype=None, name=None, doclist = None, force=0, ignore_doctypes
|
|||
webnotes.model.delete_doc.delete_doc(doctype, name, doclist, force, ignore_doctypes,
|
||||
for_reload, ignore_permissions)
|
||||
|
||||
def clear_perms(doctype):
|
||||
conn.sql("""delete from tabDocPerm where parent=%s""", doctype)
|
||||
|
||||
def reset_perms(doctype):
|
||||
clear_perms(doctype)
|
||||
reload_doc(conn.get_value("DocType", doctype, "module"), "DocType", doctype, force=True)
|
||||
|
||||
def reload_doc(module, dt=None, dn=None, plugin=None, force=False):
|
||||
import webnotes.modules
|
||||
return webnotes.modules.reload_doc(module, dt, dn, plugin=plugin, force=force)
|
||||
|
|
|
|||
|
|
@ -150,7 +150,6 @@ class Installer:
|
|||
'parenttype':'Profile', 'parentfield':'user_roles'},
|
||||
|
||||
{'doctype': "Role", "role_name": "Report Manager"},
|
||||
{'doctype': "Role", "role_name": "Restriction Manager"},
|
||||
]
|
||||
|
||||
webnotes.conn.begin()
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import webnotes
|
|||
from webnotes import _, msgprint
|
||||
from webnotes.utils import cint, cstr, flt
|
||||
from webnotes.model.doc import Document
|
||||
import webnotes.permissions
|
||||
try:
|
||||
from startup.bean_handlers import on_method
|
||||
except ImportError:
|
||||
|
|
@ -459,7 +460,7 @@ class Bean:
|
|||
|
||||
has_restricted_data = False
|
||||
for d in self.doclist:
|
||||
if not webnotes.has_only_permitted_data(webnotes.get_doctype(d.doctype), d):
|
||||
if not webnotes.permissions.has_only_permitted_data(webnotes.get_doctype(d.doctype), d):
|
||||
has_restricted_data = True
|
||||
|
||||
if has_restricted_data:
|
||||
|
|
|
|||
129
webnotes/permissions.py
Normal file
129
webnotes/permissions.py
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
from webnotes import _, msgprint, _dict
|
||||
from webnotes.utils import cint
|
||||
|
||||
def check_admin_or_system_manager():
|
||||
if ("System Manager" not in webnotes.get_roles()) and \
|
||||
(webnotes.session.user!="Administrator"):
|
||||
msgprint("Only Allowed for Role System Manager or Administrator", raise_exception=True)
|
||||
|
||||
def has_permission(doctype, ptype="read", refdoc=None):
|
||||
"""check if user has permission"""
|
||||
if webnotes.session.user=="Administrator" or webnotes.conn.get_value("DocType", doctype, "istable")==1:
|
||||
return True
|
||||
|
||||
meta = webnotes.get_doctype(doctype)
|
||||
|
||||
# get user permissions
|
||||
perms = get_user_perms(meta, ptype)
|
||||
|
||||
if not perms:
|
||||
return False
|
||||
elif refdoc:
|
||||
if isinstance(refdoc, basestring):
|
||||
refdoc = webnotes.doc(meta[0].name, refdoc)
|
||||
|
||||
if has_only_permitted_data(meta, refdoc) and has_match(perms, refdoc):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def get_user_perms(meta, ptype, user=None):
|
||||
from webnotes.utils import cint
|
||||
user_roles = webnotes.get_roles(user)
|
||||
|
||||
return [p for p in meta.get({"doctype": "DocPerm"})
|
||||
if cint(p.get(ptype))==1 and cint(p.permlevel)==0 and (p.role=="All" or p.role in user_roles)]
|
||||
|
||||
def has_only_permitted_data(meta, refdoc):
|
||||
from webnotes.defaults import get_restrictions
|
||||
|
||||
has_restricted_data = False
|
||||
restrictions = get_restrictions()
|
||||
|
||||
if restrictions:
|
||||
fields_to_check = meta.get_restricted_fields(restrictions.keys())
|
||||
|
||||
if meta[0].name in restrictions:
|
||||
fields_to_check.append(_dict({"label":"Name", "fieldname":"name", "options": meta[0].name}))
|
||||
|
||||
for df in fields_to_check:
|
||||
if refdoc.get(df.fieldname) and refdoc.get(df.fieldname) not in restrictions[df.options]:
|
||||
msg = "{not_allowed}: {doctype} {having} {label} = {value}".format(
|
||||
not_allowed=_("Sorry, you are not allowed to access"), doctype=_(df.options),
|
||||
having=_("having"), label=_(df.label), value=refdoc.get(df.fieldname))
|
||||
|
||||
if refdoc.parentfield:
|
||||
msg = "{doctype}, {row} #{idx}, ".format(doctype=_(refdoc.doctype),
|
||||
row=_("Row"), idx=refdoc.idx) + msg
|
||||
|
||||
msgprint(msg)
|
||||
has_restricted_data = True
|
||||
|
||||
if has_restricted_data:
|
||||
# check all restrictions before returning
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def has_match(perms, refdoc):
|
||||
"""check owner match (if exists)"""
|
||||
for p in perms:
|
||||
if p.get("match")=="owner":
|
||||
if refdoc.get("owner")==webnotes.local.session.user:
|
||||
# owner matches :)
|
||||
return True
|
||||
else:
|
||||
# found a permission without owner match :)
|
||||
return True
|
||||
|
||||
# no match :(
|
||||
return False
|
||||
|
||||
def can_restrict_user(user, doctype, docname=None):
|
||||
if not can_restrict(doctype, docname):
|
||||
return False
|
||||
|
||||
meta = webnotes.get_doctype(doctype)
|
||||
|
||||
# check if target user does not have restrict permission
|
||||
if has_non_restrict_role(meta, user):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def can_restrict(doctype, docname=None):
|
||||
# System Manager can always restrict
|
||||
if "System Manager" in webnotes.get_roles():
|
||||
return True
|
||||
|
||||
meta = webnotes.get_doctype(doctype)
|
||||
|
||||
# check if current user has read permission for docname
|
||||
if docname and not has_permission(doctype, "read", docname):
|
||||
return False
|
||||
|
||||
# check if current user has a role with restrict permission
|
||||
if not has_restrict_permission(meta):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def has_restrict_permission(meta=None, user=None):
|
||||
return any((perm for perm in get_user_perms(meta, "read", user)
|
||||
if cint(perm.restrict)==1))
|
||||
|
||||
def has_non_restrict_role(meta, user):
|
||||
# check if target user does not have restrict permission
|
||||
if has_restrict_permission(meta, user):
|
||||
return False
|
||||
|
||||
# and has non-restrict role
|
||||
return any((perm for perm in get_user_perms(meta, "read", user)
|
||||
if cint(perm.restrict)==0))
|
||||
|
|
@ -22,6 +22,11 @@ class Profile:
|
|||
self.can_cancel = []
|
||||
self.can_search = []
|
||||
self.can_get_report = []
|
||||
self.can_import = []
|
||||
self.can_export = []
|
||||
self.can_print = []
|
||||
self.can_email = []
|
||||
self.can_restrict = []
|
||||
self.allow_modules = []
|
||||
self.in_create = []
|
||||
|
||||
|
|
@ -43,7 +48,8 @@ class Profile:
|
|||
"""build map of permissions at level 0"""
|
||||
|
||||
self.perm_map = {}
|
||||
for r in webnotes.conn.sql("""select parent, `read`, `write`, `create`, `submit`, `cancel`, `report`
|
||||
for r in webnotes.conn.sql("""select parent, `read`, `write`, `create`, `submit`, `cancel`,
|
||||
`report`, `import`, `export`, `print`, `email`, `restrict`
|
||||
from tabDocPerm where docstatus=0
|
||||
and ifnull(permlevel,0)=0
|
||||
and parent not like "old_parent:%%"
|
||||
|
|
@ -54,7 +60,8 @@ class Profile:
|
|||
if not dt in self.perm_map:
|
||||
self.perm_map[dt] = {}
|
||||
|
||||
for k in ('read', 'write', 'create', 'submit', 'cancel', 'report'):
|
||||
for k in ('read', 'write', 'create', 'submit', 'cancel', 'report'
|
||||
'import', 'export', 'print', 'email', 'restrict'):
|
||||
if not self.perm_map[dt].get(k):
|
||||
self.perm_map[dt][k] = r.get(k)
|
||||
|
||||
|
|
@ -91,6 +98,10 @@ class Profile:
|
|||
if (p.get('read') or p.get('write') or p.get('create')):
|
||||
if p.get('report'):
|
||||
self.can_get_report.append(dt)
|
||||
for key in ("import", "export", "print", "email", "restrict"):
|
||||
if p.get(key):
|
||||
getattr(self, "can_" + key).append(dt)
|
||||
|
||||
if not dtp.get('istable'):
|
||||
if not dtp.get('issingle') and not dtp.get('read_only'):
|
||||
self.can_search.append(dt)
|
||||
|
|
@ -144,15 +155,13 @@ class Profile:
|
|||
|
||||
d['roles'] = self.get_roles()
|
||||
d['defaults'] = self.get_defaults()
|
||||
d['can_create'] = self.can_create
|
||||
d['can_write'] = self.can_write
|
||||
d['can_read'] = list(set(self.can_read))
|
||||
d['can_cancel'] = list(set(self.can_cancel))
|
||||
d['can_get_report'] = list(set(self.can_get_report))
|
||||
d['allow_modules'] = self.allow_modules
|
||||
d['all_read'] = self.all_read
|
||||
d['can_search'] = list(set(self.can_search))
|
||||
d['in_create'] = self.in_create
|
||||
|
||||
for key in ("can_create", "can_write", "can_read", "can_cancel",
|
||||
"can_get_report", "allow_modules", "all_read", "can_search",
|
||||
"in_create", "can_export", "can_import", "can_print", "can_email",
|
||||
"can_restrict"):
|
||||
|
||||
d[key] = list(set(getattr(self, key)))
|
||||
|
||||
return d
|
||||
|
||||
|
|
|
|||
|
|
@ -187,6 +187,7 @@ def build_filter_conditions(filters, conditions):
|
|||
|
||||
def build_match_conditions(doctype, fields=None, as_condition=True):
|
||||
"""add match conditions if applicable"""
|
||||
import webnotes.permissions
|
||||
match_filters = {}
|
||||
match_conditions = []
|
||||
|
||||
|
|
@ -215,7 +216,7 @@ def build_match_conditions(doctype, fields=None, as_condition=True):
|
|||
|
||||
# add owner match
|
||||
owner_match = True
|
||||
for p in webnotes.get_user_perms(webnotes.local.reportview_doctypes[doctype], "read"):
|
||||
for p in webnotes.permissions.get_user_perms(webnotes.local.reportview_doctypes[doctype], "read"):
|
||||
if not (p.match and p.match=="owner"):
|
||||
owner_match = False
|
||||
break
|
||||
|
|
|
|||
|
|
@ -38,7 +38,10 @@ class TestBlogPost(unittest.TestCase):
|
|||
webnotes.clear_cache(doctype="Blog Post")
|
||||
|
||||
profile = webnotes.bean("Profile", "test1@example.com")
|
||||
profile.get_controller().add_roles(["Website Manager"])
|
||||
profile.get_controller().add_roles("Website Manager")
|
||||
|
||||
profile = webnotes.bean("Profile", "test2@example.com")
|
||||
profile.get_controller().add_roles("Blogger")
|
||||
|
||||
webnotes.set_user("test1@example.com")
|
||||
|
||||
|
|
@ -86,7 +89,6 @@ class TestBlogPost(unittest.TestCase):
|
|||
post1 = webnotes.bean("Blog Post", "_test-blog-post-1")
|
||||
self.assertFalse(post1.has_read_perm())
|
||||
|
||||
|
||||
def test_owner_match_report(self):
|
||||
webnotes.conn.sql("""update tabDocPerm set `match`='owner' where parent='Blog Post'
|
||||
and ifnull(permlevel,0)=0""")
|
||||
|
|
@ -95,7 +97,34 @@ class TestBlogPost(unittest.TestCase):
|
|||
names = [d.name for d in webnotes.get_list("Blog Post", fields=["name", "owner"])]
|
||||
self.assertTrue("_test-blog-post" in names)
|
||||
self.assertFalse("_test-blog-post-1" in names)
|
||||
|
||||
|
||||
|
||||
def test_restrict(self):
|
||||
from core.page.user_properties.user_properties import add, remove, get_properties
|
||||
|
||||
# restrictor can add restriction
|
||||
webnotes.set_user("test1@example.com")
|
||||
add("test2@example.com", "Blog Post", "_test-blog-post")
|
||||
defname = get_properties("test2@example.com", "Blog Post", "_test-blog-post")[0].name
|
||||
|
||||
webnotes.set_user("test2@example.com")
|
||||
|
||||
# this user can't add restriction
|
||||
self.assertRaises(webnotes.PermissionError, add,
|
||||
"test2@example.com", "Blog Post", "_test-blog-post")
|
||||
|
||||
# user can only access restricted blog post
|
||||
bean = webnotes.bean("Blog Post", "_test-blog-post")
|
||||
self.assertTrue(bean.has_read_perm())
|
||||
|
||||
# and not this one
|
||||
bean = webnotes.bean("Blog Post", "_test-blog-post-1")
|
||||
self.assertFalse(bean.has_read_perm())
|
||||
|
||||
# user cannot remove their own restriction
|
||||
self.assertRaises(webnotes.PermissionError, remove,
|
||||
"test2@example.com", defname, "Blog Post", "_test-blog-post")
|
||||
|
||||
# but restrictor can
|
||||
webnotes.set_user("test1@example.com")
|
||||
remove("test2@example.com", defname, "Blog Post", "_test-blog-post")
|
||||
|
||||
Loading…
Add table
Reference in a new issue