Parcourir la source

[minor] button to manage user restrictions for a doc and report

version-14
Anand Doshi il y a 11 ans
Parent
révision
3b004ad23e
15 fichiers modifiés avec 168 ajouts et 98 suppressions
  1. +12
    -8
      core/doctype/page/page.txt
  2. +3
    -1
      core/doctype/report/report.txt
  3. +8
    -8
      core/page/permission_manager/permission_manager.py
  4. +7
    -5
      core/page/user_properties/user_properties.js
  5. +5
    -5
      core/page/user_properties/user_properties.py
  6. +8
    -4
      core/page/user_properties/user_properties.txt
  7. +23
    -11
      public/js/wn/form/infobar.js
  8. +6
    -2
      public/js/wn/misc/user.js
  9. +1
    -1
      public/js/wn/views/pageview.js
  10. +29
    -17
      public/js/wn/views/query_report.js
  11. +16
    -2
      public/js/wn/views/reportview.js
  12. +9
    -7
      webnotes/__init__.py
  13. +2
    -1
      webnotes/install_lib/install.py
  14. +30
    -24
      webnotes/widgets/page.py
  15. +9
    -2
      webnotes/widgets/query_report.py

+ 12
- 8
core/doctype/page/page.txt Voir le fichier

@@ -2,7 +2,7 @@
{
"creation": "2012-12-20 17:16:49",
"docstatus": 0,
"modified": "2013-07-11 14:37:21",
"modified": "2013-12-16 19:03:17",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -31,18 +31,13 @@
"permlevel": 0
},
{
"cancel": 0,
"create": 1,
"doctype": "DocPerm",
"name": "__common__",
"parent": "Page",
"parentfield": "permissions",
"parenttype": "DocType",
"permlevel": 0,
"read": 1,
"role": "Administrator",
"submit": 0,
"write": 1
"read": 1
},
{
"doctype": "DocType",
@@ -120,6 +115,15 @@
"search_index": 0
},
{
"doctype": "DocPerm"
"cancel": 0,
"create": 1,
"doctype": "DocPerm",
"role": "Administrator",
"submit": 0,
"write": 1
},
{
"doctype": "DocPerm",
"role": "All"
}
]

+ 3
- 1
core/doctype/report/report.txt Voir le fichier

@@ -2,7 +2,7 @@
{
"creation": "2013-03-09 15:45:57",
"docstatus": 0,
"modified": "2013-08-13 19:31:25",
"modified": "2013-12-16 17:50:35",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -132,12 +132,14 @@
},
{
"cancel": 1,
"create": 1,
"doctype": "DocPerm",
"role": "System Manager",
"write": 1
},
{
"cancel": 1,
"create": 1,
"doctype": "DocPerm",
"role": "Report Manager",
"write": 1


+ 8
- 8
core/page/permission_manager/permission_manager.py Voir le fichier

@@ -7,7 +7,7 @@ import webnotes.defaults

@webnotes.whitelist()
def get_roles_and_doctypes():
webnotes.only_for(("System Manager", "Administrator"))
webnotes.only_for("System Manager")
return {
"doctypes": [d[0] for d in webnotes.conn.sql("""select name from `tabDocType` dt where
ifnull(istable,0)=0 and
@@ -19,7 +19,7 @@ def get_roles_and_doctypes():

@webnotes.whitelist()
def get_permissions(doctype=None, role=None):
webnotes.only_for(("System Manager", "Administrator"))
webnotes.only_for("System Manager")
return webnotes.conn.sql("""select * from tabDocPerm
where %s%s order by parent, permlevel, role""" % (\
doctype and (" parent='%s'" % doctype) or "",
@@ -28,7 +28,7 @@ def get_permissions(doctype=None, role=None):
@webnotes.whitelist()
def remove(doctype, name):
webnotes.only_for(("System Manager", "Administrator"))
webnotes.only_for("System Manager")
match = webnotes.conn.get_value("DocPerm", name, "`match`")
webnotes.conn.sql("""delete from tabDocPerm where name=%s""", name)
@@ -39,7 +39,7 @@ def remove(doctype, name):

@webnotes.whitelist()
def add(parent, role, permlevel):
webnotes.only_for(("System Manager", "Administrator"))
webnotes.only_for("System Manager")
webnotes.doc(fielddata={
"doctype":"DocPerm",
"__islocal": 1,
@@ -55,7 +55,7 @@ def add(parent, role, permlevel):

@webnotes.whitelist()
def update(name, doctype, ptype, value=0):
webnotes.only_for(("System Manager", "Administrator"))
webnotes.only_for("System Manager")
webnotes.conn.sql("""update tabDocPerm set `%s`=%s where name=%s"""\
% (ptype, '%s', '%s'), (value, name))
validate_and_reset(doctype)
@@ -65,7 +65,7 @@ def update(name, doctype, ptype, value=0):
@webnotes.whitelist()
def update_match(name, doctype, match=""):
webnotes.only_for(("System Manager", "Administrator"))
webnotes.only_for("System Manager")
webnotes.conn.sql("""update tabDocPerm set `match`=%s where name=%s""",
(match, name))
validate_and_reset(doctype)
@@ -78,7 +78,7 @@ def validate_and_reset(doctype, for_remove=False):
@webnotes.whitelist()
def reset(doctype):
webnotes.only_for(("System Manager", "Administrator"))
webnotes.only_for("System Manager")
webnotes.reset_perms(doctype)
clear_doctype_cache(doctype)
webnotes.defaults.clear_cache()
@@ -92,7 +92,7 @@ def clear_doctype_cache(doctype):

@webnotes.whitelist()
def get_users_with_role(role):
webnotes.only_for(("System Manager", "Administrator"))
webnotes.only_for("System Manager")
return [p[0] for p in webnotes.conn.sql("""select distinct tabProfile.name
from tabUserRole, tabProfile where
tabUserRole.role=%s


+ 7
- 5
core/page/user_properties/user_properties.js Voir le fichier

@@ -103,7 +103,9 @@ wn.UserProperties = Class.extend({
return property=="Select Property..." ? null : property;
},
get_restriction: function() {
return this.filters.restriction.$input.val();
// autosuggest hack!
var restriction = this.filters.restriction.$input.val();
return (restriction === "%") ? null : restriction;
},
render: function(prop_list) {
this.body.empty();
@@ -157,7 +159,7 @@ wn.UserProperties = Class.extend({
$.each(this.prop_list, function(i, d) {
var row = $("<tr>").appendTo(me.table.find("tbody"));
$("<td>").html('<a href="#Form/Profile/'+d.parent+'">'
$("<td>").html('<a href="#Form/Profile/'+encodeURIComponent(d.parent)+'">'
+d.parent+'</a>').appendTo(row);
$("<td>").html(d.defkey).appendTo(row);
$("<td>").html(d.defvalue).appendTo(row);
@@ -205,7 +207,7 @@ wn.UserProperties = Class.extend({
title: "Add New Property",
fields: [
{fieldtype:"Select", label:wn._("User"),
options:me.options.users, reqd:1, fieldname:"parent"},
options:me.options.users, reqd:1, fieldname:"user"},
{fieldtype:"Select", label: wn._("Property"), fieldname:"defkey",
options:me.get_link_names(), reqd:1},
{fieldtype:"Link", label:wn._("Value"), fieldname:"defvalue",
@@ -214,8 +216,8 @@ wn.UserProperties = Class.extend({
]
});
if(me.get_user()) {
d.set_value("parent", me.get_user());
d.get_input("parent").prop("disabled", true);
d.set_value("user", me.get_user());
d.get_input("user").prop("disabled", true);
}
if(me.get_property()) {
d.set_value("defkey", me.get_property());


+ 5
- 5
core/page/user_properties/user_properties.py Voir le fichier

@@ -7,7 +7,7 @@ import webnotes.defaults

@webnotes.whitelist()
def get_users_and_links():
webnotes.only_for(("System Manager", "Administrator"))
webnotes.only_for(("Restriction Manager", "System Manager"))
return {
"users": webnotes.conn.sql_list("""select name from tabProfile where
ifnull(enabled,0)=1 and
@@ -18,7 +18,7 @@ def get_users_and_links():

@webnotes.whitelist()
def get_properties(parent=None, defkey=None, defvalue=None):
webnotes.only_for(("System Manager", "Administrator"))
webnotes.only_for(("Restriction Manager", "System Manager"))
conditions, values = _build_conditions(locals())
return webnotes.conn.sql("""select name, parent, defkey, defvalue
@@ -41,13 +41,13 @@ def _build_conditions(filters):

@webnotes.whitelist()
def remove(user, name):
webnotes.only_for(("System Manager", "Administrator"))
webnotes.only_for(("Restriction Manager", "System Manager"))
webnotes.defaults.clear_default(name=name)
@webnotes.whitelist()
def add(user, defkey, defvalue):
webnotes.only_for(("System Manager", "Administrator"))
webnotes.only_for(("Restriction Manager", "System Manager"))
# 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))


+ 8
- 4
core/page/user_properties/user_properties.txt Voir le fichier

@@ -2,7 +2,7 @@
{
"creation": "2013-01-01 18:50:55",
"docstatus": 0,
"modified": "2013-07-11 14:45:20",
"modified": "2013-12-16 16:57:12",
"modified_by": "Administrator",
"owner": "Administrator"
},
@@ -20,14 +20,18 @@
"name": "__common__",
"parent": "user-properties",
"parentfield": "roles",
"parenttype": "Page",
"role": "System Manager"
"parenttype": "Page"
},
{
"doctype": "Page",
"name": "user-properties"
},
{
"doctype": "Page Role"
"doctype": "Page Role",
"role": "System Manager"
},
{
"doctype": "Page Role",
"role": "Restriction Manager"
}
]

+ 23
- 11
public/js/wn/form/infobar.js Voir le fichier

@@ -11,44 +11,56 @@ wn.ui.form.InfoBar = Class.extend({
var me = this;

this.appframe.iconbar.clear(2);
this.$reload = this.appframe.add_icon_btn("2", "icon-refresh", "Reload Page",
this.$reload = this.appframe.add_icon_btn("2", "icon-refresh", wn._("Reload Page"),
function() { me.frm.reload_doc(); })


this.$timestamp = this.appframe.add_icon_btn("2", "icon-user", "Creation / Modified By",
this.$timestamp = this.appframe.add_icon_btn("2", "icon-user", wn._("Creation / Modified By"),
function() { })

this.$comments = this.appframe.add_icon_btn("2", "icon-comments", "Comments", function() {
this.$comments = this.appframe.add_icon_btn("2", "icon-comments", wn._("Comments"), function() {
me.scroll_to(".form-comments");
});
this.$attachments = this.appframe.add_icon_btn("2", "icon-paper-clip", "Attachments", function() {
this.$attachments = this.appframe.add_icon_btn("2", "icon-paper-clip", wn._("Attachments"), function() {
me.scroll_to(".form-attachments");
});

this.$assignments = this.appframe.add_icon_btn("2", "icon-flag", "Assignments", function() {
this.$assignments = this.appframe.add_icon_btn("2", "icon-flag", wn._("Assignments"), function() {
me.scroll_to(".form-attachments");
});


this.$links = this.appframe.add_icon_btn("2", "icon-link", "Linked With",
this.$links = this.appframe.add_icon_btn("2", "icon-link", wn._("Linked With"),
function() { me.frm.toolbar.show_linked_with(); });
// link to user restrictions
if(wn.user.can_restrict()) {
this.$user_properties = this.appframe.add_icon_btn("2", "icon-shield",
wn._("User Permission Restrictions"), function() {
wn.route_options = {
property: me.frm.doctype,
restriction: me.frm.docname
};
wn.set_route("user-properties");
});
}

if(!me.frm.meta.allow_print) {
this.$print = this.appframe.add_icon_btn("2", "icon-print", "Print",
this.$print = this.appframe.add_icon_btn("2", "icon-print", wn._("Print"),
function() { me.frm.print_doc(); });
}

if(!me.frm.meta.allow_email) {
this.$print = this.appframe.add_icon_btn("2", "icon-envelope", "Email",
this.$print = this.appframe.add_icon_btn("2", "icon-envelope", wn._("Email"),
function() { me.frm.email_doc(); });
}
if(!this.frm.meta.issingle) {
this.$prev = this.appframe.add_icon_btn("2", "icon-arrow-left", "Previous Record",
this.$prev = this.appframe.add_icon_btn("2", "icon-arrow-left", wn._("Previous Record"),
function() { me.go_prev_next(true); });
this.$next = this.appframe.add_icon_btn("2", "icon-arrow-right", "Next Record",
this.$next = this.appframe.add_icon_btn("2", "icon-arrow-right", wn._("Next Record"),
function() { me.go_prev_next(false); });
}
@@ -56,7 +68,7 @@ wn.ui.form.InfoBar = Class.extend({
refresh: function() {
if(!this.frm.doc.__islocal) {
this.docinfo = wn.model.docinfo[this.frm.doctype][this.frm.docname];
this.docinfo = wn.model.docinfo[this.frm.doctype][this.frm.docname];
// highlight comments
this.highlight_items();
}


+ 6
- 2
public/js/wn/misc/user.js Voir le fichier

@@ -124,8 +124,12 @@ $.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;
$(document).bind('mousemove', function() {


+ 1
- 1
public/js/wn/views/pageview.js Voir le fichier

@@ -42,7 +42,7 @@ wn.views.pageview = {
} else if(!wn.pages[name]) {
new wn.views.Page(name);
}
wn.container.change_to(name);
wn.container.change_to(name);
});
}
}


+ 29
- 17
public/js/wn/views/query_report.js Voir le fichier

@@ -73,6 +73,16 @@ wn.views.QueryReport = Class.extend({
var export_btn = this.appframe.add_primary_action(wn._('Export'), function() { me.export_report(); },
"icon-download");
wn.utils.disable_export_btn(export_btn);
if(wn.user.can_restrict()) {
this.appframe.add_primary_action(wn._("User Restrictions"), function() {
wn.route_options = {
property: "Report",
restriction: me.report_name
};
wn.set_route("user-properties");
}, "icon-shield");
}
},
load: function() {
// load from route
@@ -84,23 +94,25 @@ wn.views.QueryReport = Class.extend({
this.wrapper.find(".no-report-area").toggle(false);
me.appframe.set_title(wn._("Query Report")+": " + wn._(me.report_name));
if(!wn.query_reports[me.report_name]) {
return wn.call({
method:"webnotes.widgets.query_report.get_script",
args: {
report_name: me.report_name
},
callback: function(r) {
me.appframe.set_title(wn._("Query Report")+": " + wn._(me.report_name));
wn.dom.eval(r.message || "");
me.setup_filters();
me.refresh();
}
})
} else {
me.setup_filters();
me.refresh();
}
wn.model.with_doc("Report", me.report_name, function() {
if(!wn.query_reports[me.report_name]) {
return wn.call({
method:"webnotes.widgets.query_report.get_script",
args: {
report_name: me.report_name
},
callback: function(r) {
me.appframe.set_title(wn._("Query Report")+": " + wn._(me.report_name));
wn.dom.eval(r.message || "");
me.setup_filters();
me.refresh();
}
});
} else {
me.setup_filters();
me.refresh();
}
});
}
} else {
var msg = wn._("No Report Loaded. Please use query-report/[Report Name] to run a report.")


+ 16
- 2
public/js/wn/views/reportview.js Voir le fichier

@@ -101,6 +101,7 @@ wn.views.ReportView = wn.ui.Listing.extend({
this.make_export();
this.set_init_columns();
this.make_save();
this.make_user_restrictions();
this.set_tag_and_status_filter();
},

@@ -412,7 +413,7 @@ wn.views.ReportView = wn.ui.Listing.extend({
// button actions
this.page.appframe.add_button(wn._('Sort By'), function() {
me.sort_dialog.show();
}, 'icon-arrow-down');
}, 'icon-sort-by-alphabet');
$(this.sort_dialog.body).find('.btn-info').click(function() {
me.sort_dialog.hide();
@@ -470,7 +471,7 @@ wn.views.ReportView = wn.ui.Listing.extend({
wn.set_route('Report', me.doctype, r.message);
}
});
}, 'icon-upload');
}, 'icon-save');
}
},

@@ -510,6 +511,19 @@ wn.views.ReportView = wn.ui.Listing.extend({
}, 'icon-remove');
}
},
make_user_restrictions: function() {
var me = this;
if(this.docname && wn.user.can_restrict()) {
this.page.appframe.add_button(wn._("User Permission Restrictions"), function() {
wn.route_options = {
property: "Report",
restriction: me.docname
};
wn.set_route("user-properties");
}, "icon-shield");
}
},
});

wn.ui.ColumnPicker = Class.extend({


+ 9
- 7
webnotes/__init__.py Voir le fichier

@@ -346,6 +346,9 @@ def has_permission(doctype, ptype="read", refdoc=None):
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:
@@ -356,6 +359,7 @@ def has_permission(doctype, ptype="read", refdoc=None):
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)]

@@ -366,18 +370,16 @@ def has_only_permitted_data(meta, refdoc):
restrictions = get_restrictions()
if restrictions:
if isinstance(refdoc, basestring):
refdoc = doc(meta[0].name, refdoc)
fields_to_check = meta.get_restricted_fields(restrictions.keys())
if meta[0].name in restrictions:
fields_to_check.append(_dict({"label":"Name", "fieldname":"name"}))
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}: {label} {equals} {value}".format(not_allowed=_("Not allowed for"),
label=_(df.label), equals=_("equals"), value=refdoc.get(df.fieldname))
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),
@@ -416,7 +418,7 @@ def reset_metadata_version():
cache().set_value("metadata_version", v)
return v

def get_obj(dt = None, dn = None, doc=None, doclist=[], with_children = True):
def get_obj(dt = None, dn = None, doc=None, doclist=None, with_children = True):
from webnotes.model.code import get_obj
return get_obj(dt, dn, doc, doclist, with_children)



+ 2
- 1
webnotes/install_lib/install.py Voir le fichier

@@ -149,7 +149,8 @@ class Installer:
{'doctype':'UserRole', 'parent': 'Guest', 'role': 'Guest',
'parenttype':'Profile', 'parentfield':'user_roles'},
{'doctype': "Role", "role_name": "Report Manager"}
{'doctype': "Role", "role_name": "Report Manager"},
{'doctype': "Role", "role_name": "Restriction Manager"},
]
webnotes.conn.begin()


+ 30
- 24
webnotes/widgets/page.py Voir le fichier

@@ -12,8 +12,13 @@ def get(name):
Return the :term:`doclist` of the `Page` specified by `name`
"""
page = webnotes.bean("Page", name)
page.run_method("get_from_files")
return page.doclist
if has_permission(page.doclist):
page.run_method("get_from_files")
return page.doclist
else:
webnotes.response['403'] = 1
raise webnotes.PermissionError, 'No read permission for Page %s' % \
(page.doclist[0].title or name,)

@webnotes.whitelist(allow_guest=True)
def getpage():
@@ -22,32 +27,33 @@ def getpage():
"""
page = webnotes.form_dict.get('name')
doclist = get(page)

# load translations
if webnotes.lang != "en":
from webnotes.modules import get_doc_path
from webnotes.translate import get_lang_data
d = doclist[0]
messages = get_lang_data(get_doc_path(d.module, d.doctype, d.name),
webnotes.lang, 'js')
webnotes.response["__messages"] = messages
webnotes.response['docs'] = doclist
if has_permission(doclist):
# load translations
if webnotes.lang != "en":
from webnotes.modules import get_doc_path
from webnotes.translate import get_lang_data
d = doclist[0]
messages = get_lang_data(get_doc_path(d.module, d.doctype, d.name),
webnotes.lang, 'js')
webnotes.response["__messages"] = messages
webnotes.response['docs'] = doclist
else:
webnotes.response['403'] = 1
raise webnotes.PermissionError, 'No read permission for Page %s' % \
(doclist[0].title or page, )
def has_permission(page_doclist):
if webnotes.user.name == "Administrator" or "System Manager" in webnotes.user.get_roles():
return True
page_roles = [d.role for d in page_doclist if d.fields.get("doctype")=="Page Role"]
if webnotes.user.name == "Guest" and not (page_roles and "Guest" in page_roles):
return False
elif page_roles and not (set(page_roles) & set(webnotes.user.get_roles())):
if page_roles:
if webnotes.session.user == "Guest" and "Guest" not in page_roles:
return False
elif not set(page_roles).intersection(set(webnotes.get_roles())):
# check if roles match
return False
if not webnotes.has_permission("Page", ptype="read", refdoc=page_doclist[0].name):
# check if there are any restrictions
return False

return True
else:
# hack for home pages! if no page roles, allow everyone to see!
return True

+ 9
- 2
webnotes/widgets/query_report.py Voir le fichier

@@ -13,9 +13,16 @@ from webnotes.utils import flt, cint
import webnotes.widgets.reportview
import webnotes.plugins

def get_report_doc(report_name):
bean = webnotes.bean("Report", report_name)
if not bean.has_read_perm():
raise webnotes.PermissionError
return bean.doc

@webnotes.whitelist()
def get_script(report_name):
report = webnotes.doc("Report", report_name)
report = get_report_doc(report_name)
module = webnotes.conn.get_value("DocType", report.ref_doctype, "module")
module_path = get_module_path(module)
@@ -55,7 +62,7 @@ def get_script(report_name):
def run(report_name, filters=None):
from webnotes.plugins import get_code_and_execute
report = webnotes.doc("Report", report_name)
report = get_report_doc(report_name)
if filters and isinstance(filters, basestring):
filters = json.loads(filters)


Chargement…
Annuler
Enregistrer