Merge branch '4.0.0-wip' of github.com:webnotes/wnframework into 4.0.0-wip
This commit is contained in:
commit
bfc27d9306
20 changed files with 248 additions and 163 deletions
|
|
@ -105,6 +105,7 @@ def init(site, sites_path=None):
|
|||
local.app_modules = None
|
||||
local.user = None
|
||||
local.restrictions = None
|
||||
local.user_perms = {}
|
||||
|
||||
setup_module_map()
|
||||
|
||||
|
|
@ -214,6 +215,7 @@ def set_user(username):
|
|||
local.session["user"] = username
|
||||
local.user = webnotes.profile.Profile(username)
|
||||
local.restrictions = None
|
||||
local.user_perms = {}
|
||||
|
||||
def get_request_header(key, default=None):
|
||||
return request.headers.get(key, default)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
{
|
||||
"creation": "2013-02-22 01:27:33",
|
||||
"docstatus": 0,
|
||||
"modified": "2014-01-20 17:48:11",
|
||||
"modified": "2014-01-22 14:32:34",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
|
|
@ -31,19 +31,10 @@
|
|||
"name": "DocPerm"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "permlevel",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Level",
|
||||
"oldfieldname": "permlevel",
|
||||
"oldfieldtype": "Int",
|
||||
"print_width": "40px",
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"width": "40px"
|
||||
"fieldname": "role_and_level",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Role and Level"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
|
|
@ -60,6 +51,32 @@
|
|||
"search_index": 0,
|
||||
"width": "150px"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "column_break_2",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "permlevel",
|
||||
"fieldtype": "Int",
|
||||
"hidden": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Level",
|
||||
"oldfieldname": "permlevel",
|
||||
"oldfieldtype": "Int",
|
||||
"print_width": "40px",
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"width": "40px"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "section_break_4",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Permissions"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "read",
|
||||
|
|
@ -74,6 +91,13 @@
|
|||
"search_index": 0,
|
||||
"width": "32px"
|
||||
},
|
||||
{
|
||||
"description": "Only restricted users can access",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "restricted",
|
||||
"fieldtype": "Check",
|
||||
"label": "Restricted"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "write",
|
||||
|
|
@ -109,6 +133,11 @@
|
|||
"in_list_view": 1,
|
||||
"label": "Delete"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "column_break_8",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "submit",
|
||||
|
|
@ -147,6 +176,12 @@
|
|||
"print_width": "32px",
|
||||
"width": "32px"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "additional_permissions",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Additional Permissions"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "report",
|
||||
|
|
@ -167,6 +202,11 @@
|
|||
"fieldtype": "Check",
|
||||
"label": "Import"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "column_break_19",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "print",
|
||||
|
|
@ -180,21 +220,10 @@
|
|||
"label": "Email"
|
||||
},
|
||||
{
|
||||
"description": "This role can restrict users for accessing the record.",
|
||||
"doctype": "DocField",
|
||||
"fieldname": "restrict",
|
||||
"fieldtype": "Check",
|
||||
"label": "Restrict"
|
||||
},
|
||||
{
|
||||
"doctype": "DocField",
|
||||
"fieldname": "match",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"in_list_view": 1,
|
||||
"label": "Match",
|
||||
"oldfieldname": "match",
|
||||
"oldfieldtype": "Data",
|
||||
"reqd": 0,
|
||||
"search_index": 0
|
||||
"label": "Can Restrict"
|
||||
}
|
||||
]
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
{
|
||||
"creation": "2013-03-07 11:54:44",
|
||||
"docstatus": 0,
|
||||
"modified": "2014-01-20 17:49:02",
|
||||
"modified": "2014-01-22 16:05:34",
|
||||
"modified_by": "Administrator",
|
||||
"owner": "Administrator"
|
||||
},
|
||||
|
|
@ -422,10 +422,10 @@
|
|||
"delete": 0,
|
||||
"doctype": "DocPerm",
|
||||
"email": 1,
|
||||
"match": "owner",
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"report": 1,
|
||||
"restricted": 1,
|
||||
"role": "All",
|
||||
"submit": 0,
|
||||
"write": 0
|
||||
|
|
|
|||
|
|
@ -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, delete, submit, cancel, amend, report, import, export, print, email and restrict rights.")+"</li>\
|
||||
<li>"+wn._("Permissions are set on Roles and Document Types (called DocTypes) by setting read, edit, make new, delete, 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>\
|
||||
|
|
@ -38,16 +38,13 @@ wn.pages['permission-manager'].onload = function(wrapper) {
|
|||
</ol>\
|
||||
</tr></td>\
|
||||
<tr><td>\
|
||||
<h4><i class='icon-user'></i> "+wn._("Restricting By User")+":</h4>\
|
||||
<h4><i class='icon-cog'></i> "+wn._("Restricting Users")+":</h4>\
|
||||
<ol>\
|
||||
<li>"+wn._("To restrict a User of a particular Role to documents that are only self-created.")+
|
||||
wn._("Click on button in the 'Condition' column and select the option 'User is the creator of the document'")+".</li></ol>\
|
||||
</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>")+"</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>\
|
||||
<li>"+wn._("To explictly give permissions to users to specific records, check the 'Restricted' permssion. To set which user has access to which record, go to <a href='#user-properties'>User Restrictions</a>")+"</li>"+
|
||||
"<li>"+wn._("If 'Restricted' is not checked, you can still restrict permissions based on certain values, like Company or Territory in a document by setting <a href='#user-properties'>User Restrictions</a>. But unless any restriction is set, a user will have permissions based on the Role.")+"</li>"+
|
||||
"<li>"+wn._("If 'Restricted' is checked, the owner is always allowed based on Role.")+"</li>"+
|
||||
"<li>"+wn._("Once you have set this, the users will only be able access documents where the link (e.g Company) exists.")+"</li>"+
|
||||
"<li>"+wn._("Apart from System Manager, roles with Restrict permission can restrict other users for that Document Type")+"</li></ol><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>");
|
||||
|
|
@ -208,13 +205,14 @@ wn.PermissionEngine = Class.extend({
|
|||
.html(d[fieldname]);
|
||||
};
|
||||
|
||||
var add_check = function(cell, d, fieldname) {
|
||||
var add_check = function(cell, d, fieldname, label) {
|
||||
if(!label) label = fieldname;
|
||||
if(d.permlevel > 0 && ["read", "write"].indexOf(fieldname)==-1) {
|
||||
return;
|
||||
}
|
||||
|
||||
var checkbox = $("<div class='col-md-4'><div class='checkbox'>\
|
||||
<label><input type='checkbox'>"+fieldname+"</input></label>\
|
||||
<label><input type='checkbox'>"+label+"</input></label>\
|
||||
</div></div>").appendTo(cell)
|
||||
.attr("data-fieldname", fieldname)
|
||||
.css("text-transform", "capitalize");
|
||||
|
|
@ -241,6 +239,7 @@ wn.PermissionEngine = Class.extend({
|
|||
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, "restricted");
|
||||
add_check(perm_container, d, "write");
|
||||
add_check(perm_container, d, "create");
|
||||
add_check(perm_container, d, "delete");
|
||||
|
|
@ -252,7 +251,7 @@ wn.PermissionEngine = Class.extend({
|
|||
add_check(perm_container, d, "export");
|
||||
add_check(perm_container, d, "print");
|
||||
add_check(perm_container, d, "email");
|
||||
add_check(perm_container, d, "restrict");
|
||||
add_check(perm_container, d, "restrict", "Can Restrict");
|
||||
|
||||
// buttons
|
||||
me.add_match_button(row, d);
|
||||
|
|
|
|||
|
|
@ -28,9 +28,7 @@ def get_permissions(doctype=None, role=None):
|
|||
|
||||
@webnotes.whitelist()
|
||||
def remove(doctype, name):
|
||||
webnotes.only_for("System Manager")
|
||||
match = webnotes.conn.get_value("DocPerm", name, "`match`")
|
||||
|
||||
webnotes.only_for("System Manager")
|
||||
webnotes.conn.sql("""delete from tabDocPerm where name=%s""", name)
|
||||
validate_and_reset(doctype, for_remove=True)
|
||||
|
||||
|
|
@ -56,14 +54,7 @@ def update(name, doctype, ptype, value=0):
|
|||
webnotes.conn.sql("""update tabDocPerm set `%s`=%s where name=%s"""\
|
||||
% (ptype, '%s', '%s'), (value, name))
|
||||
validate_and_reset(doctype)
|
||||
|
||||
@webnotes.whitelist()
|
||||
def update_match(name, doctype, match=""):
|
||||
webnotes.only_for("System Manager")
|
||||
webnotes.conn.sql("""update tabDocPerm set `match`=%s where name=%s""",
|
||||
(match, name))
|
||||
validate_and_reset(doctype)
|
||||
|
||||
|
||||
def validate_and_reset(doctype, for_remove=False):
|
||||
from webnotes.core.doctype.doctype.doctype import validate_permissions_for_doctype
|
||||
validate_permissions_for_doctype(doctype, for_remove)
|
||||
|
|
|
|||
|
|
@ -58,6 +58,9 @@ def remove(user, name, defkey, defvalue):
|
|||
|
||||
webnotes.defaults.clear_default(name=name)
|
||||
|
||||
def clear_restrictions(doctype):
|
||||
webnotes.defaults.clear_default(parenttype="Restriction", key=doctype)
|
||||
|
||||
@webnotes.whitelist()
|
||||
def add(user, defkey, defvalue):
|
||||
if not webnotes.permissions.can_restrict_user(user, defkey, defvalue):
|
||||
|
|
|
|||
|
|
@ -459,7 +459,7 @@ class Bean:
|
|||
|
||||
has_restricted_data = False
|
||||
for d in self.doclist:
|
||||
if not webnotes.permissions.has_only_permitted_data(webnotes.get_doctype(d.doctype), d):
|
||||
if not webnotes.permissions.has_unrestricted_access(webnotes.get_doctype(d.doctype), d):
|
||||
has_restricted_data = True
|
||||
|
||||
if has_restricted_data:
|
||||
|
|
|
|||
|
|
@ -400,6 +400,12 @@ class DocTypeDocList(webnotes.model.doclist.DocList):
|
|||
if self[0].name in restricted_types:
|
||||
restricted_fields.append(webnotes._dict({"label":"Name", "fieldname":"name", "options": self[0].name}))
|
||||
return restricted_fields
|
||||
|
||||
def get_permissions(self, user=None):
|
||||
user_roles = webnotes.get_roles(user)
|
||||
return [p for p in self.get({"doctype": "DocPerm"})
|
||||
if cint(p.permlevel)==0 and (p.role=="All" or p.role in user_roles)]
|
||||
|
||||
|
||||
def rename_field(doctype, old_fieldname, new_fieldname, lookup_field=None):
|
||||
"""this function assumes that sync is NOT performed"""
|
||||
|
|
|
|||
|
|
@ -5,4 +5,5 @@ execute:webnotes.reload_doc('core', 'doctype', 'page') #2013-13-26
|
|||
execute:webnotes.reload_doc('core', 'doctype', 'report') #2013-13-26
|
||||
|
||||
webnotes.patches.4_0.remove_index_sitemap
|
||||
webnotes.patches.4_0.add_delete_permission
|
||||
webnotes.patches.4_0.add_delete_permission
|
||||
webnotes.patches.4_0.move_match_to_restricted
|
||||
|
|
@ -7,6 +7,6 @@ def execute():
|
|||
webnotes.conn.sql("""update tabDocPerm set `delete`=ifnull(`cancel`,0)""")
|
||||
|
||||
# can't cancel if can't submit
|
||||
webnotes.conn.sql("""update tabDocPerm set `cancel`=0 where `submit`=0""")
|
||||
webnotes.conn.sql("""update tabDocPerm set `cancel`=0 where ifnull(`submit`,0)=0""")
|
||||
|
||||
webnotes.clear_cache()
|
||||
9
webnotes/patches/4_0/move_match_to_restricted.py
Normal file
9
webnotes/patches/4_0/move_match_to_restricted.py
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
|
||||
# MIT License. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import webnotes
|
||||
|
||||
def execute():
|
||||
webnotes.reload_doc("core", "doctype", "docperm")
|
||||
webnotes.conn.sql("""update `tabDocPerm` set restricted=1 where `match`='owner'""")
|
||||
|
|
@ -26,35 +26,57 @@ def has_permission(doctype, ptype="read", refdoc=None, verbose=True):
|
|||
|
||||
if webnotes.session.user=="Administrator":
|
||||
return True
|
||||
|
||||
|
||||
# get user permissions
|
||||
perms = get_user_perms(meta, ptype)
|
||||
|
||||
if not perms:
|
||||
if not get_user_perms(meta).get(ptype):
|
||||
return False
|
||||
elif refdoc:
|
||||
if isinstance(refdoc, basestring):
|
||||
refdoc = webnotes.doc(meta[0].name, refdoc)
|
||||
|
||||
if (has_only_permitted_data(meta, refdoc, verbose=verbose) and has_match(perms, refdoc)):
|
||||
if has_unrestricted_access(meta, refdoc, verbose=verbose):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def get_user_perms(meta, ptype, user=None):
|
||||
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)]
|
||||
rights = ["read", "write", "create", "submit", "cancel", "amend",
|
||||
"report", "import", "export", "print", "email", "restrict", "delete", "restricted"]
|
||||
|
||||
def has_only_permitted_data(meta, refdoc, verbose=True):
|
||||
def get_user_perms(meta, user=None):
|
||||
cache_key = (meta[0].name, user)
|
||||
if not webnotes.local.user_perms.get(cache_key):
|
||||
perms = webnotes._dict()
|
||||
user_roles = webnotes.get_roles(user)
|
||||
|
||||
for p in meta.get({"doctype": "DocPerm"}):
|
||||
if cint(p.permlevel)==0 and (p.role=="All" or p.role in user_roles):
|
||||
for ptype in rights:
|
||||
if ptype == "restricted":
|
||||
perms[ptype] = perms.get(ptype, 1) and cint(p.get(ptype))
|
||||
else:
|
||||
perms[ptype] = perms.get(ptype, 0) or cint(p.get(ptype))
|
||||
|
||||
webnotes.local.user_perms[cache_key] = perms
|
||||
|
||||
return webnotes.local.user_perms[cache_key]
|
||||
|
||||
def has_unrestricted_access(meta, refdoc, verbose=True):
|
||||
from webnotes.defaults import get_restrictions
|
||||
restrictions = get_restrictions()
|
||||
if not restrictions:
|
||||
return True
|
||||
|
||||
if get_user_perms(meta).restricted:
|
||||
if refdoc.owner == webnotes.session.user:
|
||||
# owner is always allowed for restricted permissions
|
||||
return True
|
||||
elif not restrictions:
|
||||
return False
|
||||
else:
|
||||
if not restrictions:
|
||||
return True
|
||||
|
||||
# evaluate specific restrictions
|
||||
fields_to_check = meta.get_restricted_fields(restrictions.keys())
|
||||
|
||||
has_restricted_data = False
|
||||
|
|
@ -75,20 +97,6 @@ def has_only_permitted_data(meta, refdoc, verbose=True):
|
|||
|
||||
# check all restrictions before returning
|
||||
return False if has_restricted_data else 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):
|
||||
|
|
@ -106,7 +114,6 @@ 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
|
||||
|
|
@ -120,8 +127,7 @@ def can_restrict(doctype, docname=None):
|
|||
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))
|
||||
return get_user_perms(meta, user).restrict==1
|
||||
|
||||
def has_only_non_restrict_role(meta, user):
|
||||
# check if target user does not have restrict permission
|
||||
|
|
@ -129,8 +135,7 @@ def has_only_non_restrict_role(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))
|
||||
return get_user_perms(meta, user).restrict==0
|
||||
|
||||
def can_import(doctype, raise_exception=False):
|
||||
if not ("System Manager" in webnotes.get_roles() or has_permission(doctype, "import")):
|
||||
|
|
|
|||
2
webnotes/public/css/bootstrap.css
vendored
2
webnotes/public/css/bootstrap.css
vendored
|
|
@ -1699,7 +1699,7 @@ output {
|
|||
border-radius: 4px;
|
||||
}
|
||||
.form-control:focus {
|
||||
border-color: #000;
|
||||
border-color: #66afe9;
|
||||
outline: 0;
|
||||
}
|
||||
.form-control:-moz-placeholder {
|
||||
|
|
|
|||
|
|
@ -465,7 +465,7 @@ wn.ui.form.ControlCheck = wn.ui.form.ControlData.extend({
|
|||
<label>\
|
||||
<span class="input-area"></span>\
|
||||
<span class="disp-area" style="display:none;"></span>\
|
||||
<span class="label-area small text-muted"></span>\
|
||||
<span class="label-area small"></span>\
|
||||
</label>\
|
||||
<p class="help-box small text-muted"></p>\
|
||||
</div>\
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ var SUBMIT = "submit", CANCEL = "cancel", AMEND = "amend";
|
|||
|
||||
$.extend(wn.perm, {
|
||||
rights: ["read", "write", "create", "submit", "cancel", "amend",
|
||||
"report", "import", "export", "print", "email", "restrict", "delete"],
|
||||
"report", "import", "export", "print", "email", "restrict", "delete", "restricted"],
|
||||
|
||||
doctype_perm: {},
|
||||
|
||||
|
|
@ -55,7 +55,7 @@ $.extend(wn.perm, {
|
|||
perm[0].read = 1;
|
||||
}
|
||||
|
||||
if(docname && !wn.perm.has_only_permitted_data(doctype, docname)) {
|
||||
if(docname && !wn.perm.has_unrestricted_access(doctype, docname, perm[0].restricted)) {
|
||||
// if has restricted data, return not permitted
|
||||
return perm;
|
||||
}
|
||||
|
|
@ -63,14 +63,17 @@ $.extend(wn.perm, {
|
|||
var docperms = wn.model.get("DocPerm", {parent: doctype});
|
||||
$.each(docperms, function(i, p) {
|
||||
// if user has this role
|
||||
if(user_roles.indexOf(p.role)!==-1 &&
|
||||
(!docname || wn.perm.has_match(p, doctype, docname))) {
|
||||
if(user_roles.indexOf(p.role)!==-1) {
|
||||
var permlevel = cint(p.permlevel);
|
||||
if(!perm[permlevel]) {
|
||||
perm[permlevel] = {};
|
||||
}
|
||||
$.each(wn.perm.rights, function(i, key) {
|
||||
perm[permlevel][key] = perm[permlevel][key] || (p[key] || 0);
|
||||
if(key=="restricted") {
|
||||
perm[permlevel][key] = (perm[permlevel][key] || 1) && (p[key] || 0);
|
||||
} else {
|
||||
perm[permlevel][key] = perm[permlevel][key] || (p[key] || 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
@ -78,10 +81,19 @@ $.extend(wn.perm, {
|
|||
return perm;
|
||||
},
|
||||
|
||||
has_only_permitted_data: function(doctype, docname) {
|
||||
has_unrestricted_access: function(doctype, docname, restricted) {
|
||||
var restrictions = wn.defaults.get_restrictions();
|
||||
if(!restrictions || $.isEmptyObject(restrictions)) {
|
||||
return true;
|
||||
var doc = wn.model.get_doc(doctype, docname);
|
||||
|
||||
if(restricted) {
|
||||
if(doc.owner==user) return true;
|
||||
if(!restrictions || $.isEmptyObject(restrictions)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if(!restrictions || $.isEmptyObject(restrictions)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// prepare restricted fields
|
||||
|
|
@ -109,33 +121,10 @@ $.extend(wn.perm, {
|
|||
}
|
||||
return fields_to_check;
|
||||
},
|
||||
|
||||
has_match: function(docperm, doctype, docname) {
|
||||
if(!docperm.match) return true;
|
||||
if(docperm.match==="owner") {
|
||||
var doc = wn.model.get_doc(doctype, docname);
|
||||
if(doc.owner===user) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
|
||||
get_match_rules: function(doctype) {
|
||||
var match_rules = {};
|
||||
|
||||
// Rule for owner match
|
||||
var owner_match = false;
|
||||
$.each(wn.model.get("DocPerm", {parent:doctype}), function(i, docperm) {
|
||||
if(docperm.match==="owner") {
|
||||
owner_match = true;
|
||||
} else {
|
||||
owner_match = false;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if(owner_match) match_rules["Created By"] = user;
|
||||
|
||||
|
||||
// Rule for restrictions
|
||||
var restrictions = wn.defaults.get_restrictions();
|
||||
if(restrictions && !$.isEmptyObject(restrictions)) {
|
||||
|
|
|
|||
|
|
@ -68,9 +68,6 @@ wn.request.call = function(opts) {
|
|||
opts.success && opts.success(data, xhr.responseText);
|
||||
}
|
||||
},
|
||||
fail: function(xhr, textStatus) {
|
||||
opts.error && opts.error(xhr)
|
||||
},
|
||||
async: opts.async
|
||||
};
|
||||
|
||||
|
|
@ -100,7 +97,14 @@ wn.request.call = function(opts) {
|
|||
})
|
||||
}
|
||||
|
||||
return $.ajax(ajax_args).always(function(data) {
|
||||
return $.ajax(ajax_args)
|
||||
.fail(function(xhr, textStatus) {
|
||||
opts.error && opts.error(xhr)
|
||||
})
|
||||
.always(function(data) {
|
||||
if(data.responseText) {
|
||||
data = JSON.parse(data.responseText);
|
||||
}
|
||||
wn.request.cleanup(opts, data);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,6 +104,8 @@ wn.views.DocListView = wn.ui.Listing.extend({
|
|||
show_match_help: function() {
|
||||
var me = this;
|
||||
var match_rules = wn.perm.get_match_rules(this.doctype);
|
||||
var perm = wn.perm.get_perm(doctype);
|
||||
|
||||
if(keys(match_rules).length) {
|
||||
var match_text = []
|
||||
$.each(match_rules, function(key, values) {
|
||||
|
|
@ -113,6 +115,10 @@ wn.views.DocListView = wn.ui.Listing.extend({
|
|||
match_text.push(wn._(key) + " = " + wn.utils.comma_or(values));
|
||||
}
|
||||
});
|
||||
|
||||
if(perm[0].restricted) {
|
||||
match_text.push(wn._("Or Created By") + " = " + user);
|
||||
}
|
||||
wn.utils.set_footnote(this, this.$page.find(".layout-main-section"),
|
||||
"<p>" + wn._("Showing only for") + ":</p><ul>"
|
||||
+ $.map(match_text, function(txt) { return "<li>"+txt+"</li>" }).join("")) + "</ul>";
|
||||
|
|
|
|||
|
|
@ -26,13 +26,15 @@ test_records = [
|
|||
import webnotes
|
||||
import webnotes.defaults
|
||||
import unittest
|
||||
from webnotes.core.page.user_properties.user_properties import add, remove, get_properties, clear_restrictions
|
||||
|
||||
|
||||
test_dependencies = ["Profile"]
|
||||
class TestBlogPost(unittest.TestCase):
|
||||
def setUp(self):
|
||||
webnotes.conn.sql("""update tabDocPerm set `match`='' where parent='Blog Post'
|
||||
webnotes.conn.sql("""update tabDocPerm set `restricted`=0 where parent='Blog Post'
|
||||
and ifnull(permlevel,0)=0""")
|
||||
webnotes.conn.sql("""update `tabBlog Post` set owner='test1@example.com'
|
||||
webnotes.conn.sql("""update `tabBlog Post` set owner='test2@example.com'
|
||||
where name='_test-blog-post'""")
|
||||
|
||||
webnotes.clear_cache(doctype="Blog Post")
|
||||
|
|
@ -47,7 +49,8 @@ class TestBlogPost(unittest.TestCase):
|
|||
|
||||
def tearDown(self):
|
||||
webnotes.set_user("Administrator")
|
||||
webnotes.defaults.clear_default(key="Blog Category", parenttype="Restriction")
|
||||
clear_restrictions("Blog Category")
|
||||
clear_restrictions("Blog Post")
|
||||
|
||||
def test_basic_permission(self):
|
||||
post = webnotes.bean("Blog Post", "_test-blog-post")
|
||||
|
|
@ -79,12 +82,17 @@ class TestBlogPost(unittest.TestCase):
|
|||
|
||||
doc = webnotes.new_doc("Blog Post")
|
||||
self.assertEquals(doc.get("blog_category"), "_Test Blog Category 1")
|
||||
|
||||
def test_owner_match_bean(self):
|
||||
webnotes.conn.sql("""update tabDocPerm set `match`='owner' where parent='Blog Post'
|
||||
|
||||
def add_restricted_on_blogger(self):
|
||||
webnotes.conn.sql("""update tabDocPerm set `restricted`=1 where parent='Blog Post' and role='Blogger'
|
||||
and ifnull(permlevel,0)=0""")
|
||||
webnotes.clear_cache(doctype="Blog Post")
|
||||
|
||||
|
||||
def test_owner_match_bean(self):
|
||||
self.add_restricted_on_blogger()
|
||||
|
||||
webnotes.set_user("test2@example.com")
|
||||
|
||||
post = webnotes.bean("Blog Post", "_test-blog-post")
|
||||
self.assertTrue(post.has_read_perm())
|
||||
|
||||
|
|
@ -92,28 +100,36 @@ class TestBlogPost(unittest.TestCase):
|
|||
self.assertFalse(post1.has_read_perm())
|
||||
|
||||
def test_owner_match_report(self):
|
||||
webnotes.conn.sql("""update tabDocPerm set `match`='owner' where parent='Blog Post'
|
||||
webnotes.conn.sql("""update tabDocPerm set `restricted`=1 where parent='Blog Post'
|
||||
and ifnull(permlevel,0)=0""")
|
||||
webnotes.clear_cache(doctype="Blog Post")
|
||||
|
||||
webnotes.set_user("test2@example.com")
|
||||
|
||||
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 webnotes.core.page.user_properties.user_properties import add, remove, get_properties
|
||||
|
||||
# restrictor can add restriction
|
||||
|
||||
def add_restriction_to_user2(self):
|
||||
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
|
||||
|
||||
def test_add_restriction(self):
|
||||
# restrictor can add restriction
|
||||
self.add_restriction_to_user2()
|
||||
|
||||
def test_not_allowed_to_restrict(self):
|
||||
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")
|
||||
|
||||
|
||||
def test_not_allowed_to_restrict(self):
|
||||
self.add_restriction_to_user2()
|
||||
|
||||
webnotes.set_user("test2@example.com")
|
||||
|
||||
# user can only access restricted blog post
|
||||
bean = webnotes.bean("Blog Post", "_test-blog-post")
|
||||
self.assertTrue(bean.has_read_perm())
|
||||
|
|
@ -121,12 +137,28 @@ class TestBlogPost(unittest.TestCase):
|
|||
# and not this one
|
||||
bean = webnotes.bean("Blog Post", "_test-blog-post-1")
|
||||
self.assertFalse(bean.has_read_perm())
|
||||
|
||||
|
||||
def test_not_allowed_to_remove_self(self):
|
||||
self.add_restriction_to_user2()
|
||||
defname = get_properties("test2@example.com", "Blog Post", "_test-blog-post")[0].name
|
||||
|
||||
webnotes.set_user("test2@example.com")
|
||||
|
||||
# user cannot remove their own restriction
|
||||
self.assertRaises(webnotes.PermissionError, remove,
|
||||
"test2@example.com", defname, "Blog Post", "_test-blog-post")
|
||||
|
||||
# but restrictor can
|
||||
|
||||
def test_allow_in_restriction(self):
|
||||
self.add_restricted_on_blogger()
|
||||
|
||||
webnotes.set_user("test2@example.com")
|
||||
bean = webnotes.bean("Blog Post", "_test-blog-post-1")
|
||||
self.assertFalse(bean.has_read_perm())
|
||||
|
||||
webnotes.set_user("test1@example.com")
|
||||
remove("test2@example.com", defname, "Blog Post", "_test-blog-post")
|
||||
|
||||
add("test2@example.com", "Blog Post", "_test-blog-post-1")
|
||||
|
||||
webnotes.set_user("test2@example.com")
|
||||
bean = webnotes.bean("Blog Post", "_test-blog-post-1")
|
||||
|
||||
self.assertTrue(bean.has_read_perm())
|
||||
|
|
|
|||
|
|
@ -120,9 +120,12 @@ def get_filtered_data(ref_doctype, columns, data):
|
|||
matched_columns = get_matched_columns(linked_doctypes, match_filters)
|
||||
for row in data:
|
||||
match = True
|
||||
for col, idx in matched_columns.items():
|
||||
if row[idx] not in match_filters[col]:
|
||||
match = False
|
||||
|
||||
if not ("owner" in match_filters and matched_columns.get("profile", None)==match_filters["owner"]):
|
||||
for col, idx in matched_columns.items():
|
||||
if row[idx] not in match_filters[col]:
|
||||
match = False
|
||||
break
|
||||
|
||||
if match:
|
||||
result.append(row)
|
||||
|
|
|
|||
|
|
@ -204,15 +204,24 @@ def build_match_conditions(doctype, fields=None, as_condition=True):
|
|||
import webnotes.permissions
|
||||
match_filters = {}
|
||||
match_conditions = []
|
||||
or_conditions = []
|
||||
|
||||
if not getattr(webnotes.local, "reportview_tables", None):
|
||||
webnotes.local.reportview_tables = get_tables(doctype, fields)
|
||||
|
||||
load_doctypes()
|
||||
|
||||
# is restricted
|
||||
restricted = webnotes.permissions.get_user_perms(webnotes.local.reportview_doctypes[doctype]).restricted
|
||||
|
||||
# get restrictions
|
||||
restrictions = webnotes.defaults.get_restrictions()
|
||||
|
||||
if restricted:
|
||||
or_conditions.append('`tab{doctype}`.`owner`="{user}"'.format(doctype=doctype,
|
||||
user=webnotes.local.session.user))
|
||||
match_filters["owner"] = webnotes.session.user
|
||||
|
||||
if restrictions:
|
||||
fields_to_check = webnotes.local.reportview_doctypes[doctype].get_restricted_fields(restrictions.keys())
|
||||
if doctype in restrictions:
|
||||
|
|
@ -223,28 +232,25 @@ def build_match_conditions(doctype, fields=None, as_condition=True):
|
|||
if as_condition:
|
||||
match_conditions.append('`tab{doctype}`.{fieldname} in ({values})'.format(doctype=doctype,
|
||||
fieldname=df.fieldname,
|
||||
values=", ".join([('"'+v.replace('"', '\"')+'"') for v in restrictions[df.options]])))
|
||||
values=", ".join([('"'+v.replace('"', '\"')+'"') \
|
||||
for v in restrictions[df.options]])))
|
||||
else:
|
||||
match_filters.setdefault(df.fieldname, [])
|
||||
match_filters[df.fieldname]= restrictions[df.options]
|
||||
|
||||
# add owner match
|
||||
owner_match = True
|
||||
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
|
||||
|
||||
if owner_match:
|
||||
match_conditions.append('`tab{doctype}`.`owner`="{user}"'.format(doctype=doctype,
|
||||
user=webnotes.local.session.user))
|
||||
match_filters["owner"] = [webnotes.local.session.user]
|
||||
|
||||
|
||||
if as_condition:
|
||||
conditions = " and ".join(match_conditions)
|
||||
doctype_conditions = get_doctype_conditions(doctype)
|
||||
if doctype_conditions:
|
||||
conditions += ' and ' + doctype_conditions if conditions else doctype_conditions
|
||||
|
||||
if or_conditions:
|
||||
if conditions:
|
||||
conditions = '({conditions}) or {or_conditions}'.format(conditions=conditions,
|
||||
or_conditions = ' or '.join(or_conditions))
|
||||
else:
|
||||
conditions = " or ".join(or_conditions)
|
||||
|
||||
return conditions
|
||||
else:
|
||||
return match_filters
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue