new permission manager

This commit is contained in:
Rushabh Mehta 2013-01-01 19:51:35 +05:30
parent 5054a6848f
commit 9a6e3cf620
13 changed files with 894 additions and 14 deletions

View file

@ -72,7 +72,8 @@ class DocType:
webnotes.msgprint(c + " not allowed in name", raise_exception=1)
self.validate_series()
self.scrub_field_names()
validate_fields(filter(lambda d: d.doctype=="DocField", self.doclist))
validate_fields(self.doclist.get({"doctype":"DocField"}))
validate_permissions(self.doclist.get({"doctype":"DocPerm"}))
self.set_version()
def on_update(self):
@ -165,9 +166,9 @@ class DocType:
def validate_fields_for_doctype(doctype):
from webnotes.model.doctype import get
validate_fields(filter(lambda d: d.doctype=="DocField" and d.parent==doctype,
get(doctype, cached=False)))
validate_fields(get(doctype, cached=False).get({"parent":doctype,
"doctype":"DocField"}))
def validate_fields(fields):
def check_illegal_characters(fieldname):
for c in ['.', ',', ' ', '-', '&', '%', '=', '"', "'", '*', '$',
@ -211,4 +212,62 @@ def validate_fields(fields):
check_illegal_mandatory(d)
check_link_table_options(d)
check_hidden_and_mandatory(d)
def validate_permissions_for_doctype(doctype, for_remove=False):
from webnotes.model.doctype import get
validate_permissions(get(doctype, cached=False).get({"parent":doctype,
"doctype":"DocPerm"}), for_remove)
def validate_permissions(permissions, for_remove=False):
def get_txt(d):
return "For %s (level %s) in %s:" % (d.role, d.permlevel, d.parent)
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:
webnotes.msgprint(get_txt(d) + " Atleast one of Read, Write, Create, Submit, Cancel must be set.",
raise_exception=True)
def check_double(d):
similar = permissions.get({
"role":d.role,
"permlevel":d.permlevel,
"match": d.match
})
if len(similar) > 1:
webnotes.msgprint(get_txt(d) + " Only one rule allowed for a particular Role and Level.",
raise_exception=True)
def check_level_zero_is_set(d):
if d.permlevel > 0 and d.role != 'All':
if not permissions.get({"role": d.role, "permlevel": 0}):
webnotes.msgprint(get_txt(d) + " Higher level permissions are meaningless if level 0 permission is not set.",
raise_exception=True)
if d.create:
webnotes.msgprint("Create Permission has no meaning at level " + d.permlevel,
raise_exception=True)
if d.submit:
webnotes.msgprint("Submit Permission has no meaning at level " + d.permlevel,
raise_exception=True)
if d.cancel:
webnotes.msgprint("Cancel Permission has no meaning at level " + d.permlevel,
raise_exception=True)
if d.amend:
webnotes.msgprint("Amend Permission has no meaning at level " + d.permlevel,
raise_exception=True)
if d.match:
webnotes.msgprint("Match rules have no meaning at level " + d.permlevel,
raise_exception=True)
for d in permissions:
if not d.permlevel: d.permlevel=0
check_atleast_one_set(d)
if not for_remove:
check_double(d)
check_level_zero_is_set(d)

View file

View file

@ -0,0 +1,445 @@
wn.pages['permission-manager'].onload = function(wrapper) {
wn.ui.make_app_page({
parent: wrapper,
title: 'Permission Manager',
single_column: true
});
wrapper.permission_engine = new wn.PermissionEngine(wrapper);
}
wn.pages['permission-manager'].refresh = function(wrapper) {
wrapper.permission_engine.set_from_route();
}
wn.PermissionEngine = Class.extend({
init: function(wrapper) {
this.wrapper = wrapper;
this.body = $(this.wrapper).find(".layout-main");
this.make();
this.refresh();
this.add_check_events();
},
make: function() {
var me = this;
me.make_reset_button();
wn.call({
module:"core",
page:"permission_manager",
method: "get_roles_and_doctypes",
callback: function(r) {
me.options = r.message;
me.doctype_select
= me.wrapper.appframe.add_select("doctypes",
["Select Document Type..."].concat(r.message.doctypes))
.css("width", "200px")
.change(function() {
wn.set_route("permission-manager", $(this).val())
});
me.role_select
= me.wrapper.appframe.add_select("roles",
["Select Role..."].concat(r.message.roles))
.css("width", "200px")
.change(function() {
me.refresh();
});
me.set_from_route();
}
});
},
set_from_route: function() {
if(wn.get_route()[1] && this.doctype_select) {
this.doctype_select.val(wn.get_route()[1]);
this.refresh();
} else {
this.refresh();
}
},
make_reset_button: function() {
var me = this;
me.reset_button = me.wrapper.appframe.add_button("Reset Permissions", function() {
if(wn.confirm("Reset Permissions for " + me.get_doctype() + "?", function() {
wn.call({
module:"core",
page:"permission_manager",
method:"reset",
args: {
doctype:me.get_doctype(),
},
callback: function() { me.refresh(); }
});
}));
}, 'icon-retweet');
},
get_doctype: function() {
var doctype = this.doctype_select.val();
return doctype=="Select Document Type..." ? null : doctype;
},
get_role: function() {
var role = this.role_select.val();
return role=="Select Role..." ? null : role;
},
refresh: function() {
var me = this;
if(!me.doctype_select) {
this.body.html("<div class='alert'>Loading...</div>");
return;
}
if(!me.get_doctype() && !me.get_role()) {
this.body.html("<div class='alert'>Select Document Type or Role to start.</div>");
return;
}
// get permissions
wn.call({
module: "core",
page: "permission_manager",
method: "get_permissions",
args: {
doctype: me.get_doctype(),
role: me.get_role()
},
callback: function(r) {
me.render(r.message);
}
});
me.reset_button.toggle(me.get_doctype() ? true : false);
},
render: function(perm_list) {
this.body.empty();
this.perm_list = perm_list;
if(!perm_list.length) {
this.body.html("<div class='alert'>No Permissions set for this criteria.</div>");
} else {
this.show_permission_table(perm_list);
}
this.show_add_rule();
this.show_explain();
},
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);
$.each([["Document Type", 150], ["Role", 100], ["Level",50],
["Read", 50], ["Write", 50], ["Create", 50],
["Submit", 50], ["Cancel", 50], ["Amend", 50],
["Condition", 150], ["", 50]], 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'>")
.attr("checked", d[fieldname] ? "checked": null)
.attr("data-ptype", fieldname)
.attr("data-name", d.name)
.attr("data-doctype", d.parent)
.appendTo(cell);
}
} else {
cell.html(d[fieldname]);
}
return cell;
}
$.each(perm_list, function(i, d) {
if(!d.permlevel) d.permlevel = 0;
var row = $("<tr>").appendTo(me.table.find("tbody"));
add_cell(row, d, "parent");
add_cell(row, d, "role");
var cell = add_cell(row, d, "permlevel");
if(d.permlevel==0) {
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);
// buttons
me.add_match_button(row, d);
me.add_delete_button(row, d);
});
},
add_match_button: function(row, d) {
var me = this;
if(d.permlevel > 0) {
$("<td>-</td>").appendTo(row);
return;
}
var btn = $("<button class='btn btn-small'></button>")
.html(d.match ? d.match : "For All Users")
.appendTo($("<td>").appendTo(row))
.attr("data-name", d.name)
.click(function() {
me.show_match_manager($(this).attr("data-name"));
});
if(d.match) btn.addClass("btn-inverse");
},
add_delete_button: function(row, d) {
var me = this;
$("<button class='btn btn-small'><i class='icon-remove'></i></button>")
.appendTo($("<td>").appendTo(row))
.attr("data-name", d.name)
.attr("data-doctype", d.parent)
.click(function() {
wn.call({
module: "core",
page: "permission_manager",
method: "remove",
args: {
name: $(this).attr("data-name"),
doctype: $(this).attr("data-doctype")
},
callback: function(r) {
if(r.exc) {
msgprint("Did not remove.");
} else {
me.refresh();
}
}
})
});
},
add_check_events: function() {
var me = this;
this.body.on("click", "input[type='checkbox']", function() {
var chk = $(this);
var args = {
name: chk.attr("data-name"),
doctype: chk.attr("data-doctype"),
ptype: chk.attr("data-ptype"),
value: chk.is(":checked") ? 1 : 0
}
wn.call({
module: "core",
page: "permission_manager",
method: "update",
args: args,
callback: function(r) {
if(r.exc) {
// exception: reverse
chk.attr("checked", chk.is(":checked") ? null : "checked");
} else {
me.get_perm(args.name)[args.ptype]=args.value;
me.show_explain();
}
}
})
})
},
show_add_rule: function() {
var me = this;
$("<button class='btn btn-info'>Add A New Rule</button>")
.appendTo($("<p>").appendTo(this.body))
.click(function() {
var d = new wn.ui.Dialog({
title: "Add New Permission Rule",
fields: [
{fieldtype:"Select", label:"Document Type",
options:me.options.doctypes, reqd:1, fieldname:"parent"},
{fieldtype:"Select", label:"Role",
options:me.options.roles, reqd:1},
{fieldtype:"Select", label:"Permission Level",
options:[0,1,2,3,4,5,6,7,8,9], reqd:1, fieldname: "permlevel",
description:"Level 0 is for document level permissions, higher levels for field level permissions."},
{fieldtype:"Button", label:"Add"},
]
});
if(me.get_doctype()) {
d.set_value("parent", me.get_doctype());
d.get_input("parent").attr("disabled", true);
}
if(me.get_role()) {
d.set_value("role", me.get_role());
d.get_input("role").attr("disabled", true);
}
d.set_value("permlevel", "0");
d.get_input("add").click(function() {
var args = d.get_values();
if(!args) {
return;
}
wn.call({
module: "core",
page: "permission_manager",
method: "add",
args: args,
callback: function(r) {
if(r.exc) {
msgprint("Did not add.");
} else {
me.refresh();
}
}
})
d.hide();
});
d.show();
});
},
get_perm: function(name) {
return $.map(this.perm_list, function(d) { if(d.name==name) return d; })[0];
},
show_match_manager:function(name) {
var perm = this.get_perm(name);
var me = this;
wn.model.with_doctype(perm.parent, function() {
var dialog = new wn.ui.Dialog({
title: "Applies for Users",
});
$(dialog.body).html("<h4>Rule Applies to Following Users:</h4>\
<label class='radio'>\
<input name='perm-rule' type='radio' value=''> All users with role <b>"+perm.role+"</b>.\
</label>\
<label class='radio'>\
<input name='perm-rule' type='radio' value='owner'> The user is the creator of the document.\
</label>").css("padding", "15px");
// profile fields
$.each(me.get_profile_fields(perm.parent), function(i, d) {
$("<label class='radio'>\
<input name='perm-rule' type='radio' value='"+d.fieldname
+":user'>Value of field <b>"+d.label+"</b> is the User.\
</label>").appendTo(dialog.body);
});
// add options for all link fields
$.each(me.get_link_fields(perm.parent), function(i, d) {
$("<label class='radio'>\
<input name='perm-rule' type='radio' value='"+d.fieldname
+"'><b>"+d.label+"</b> in <b>"+d.parent+"</b> matches <a href='#user-properties'>User Property</a> <b>"
+d.fieldname+"</b>.\
</label>").appendTo(dialog.body);
});
// button
$("<button class='btn btn-info'>Update</button>")
.appendTo($("<p>").appendTo(dialog.body))
.attr("data-name", perm.name)
.click(function() {
var match_value = $(dialog.wrapper).find(":radio:checked").val();
var perm = me.get_perm($(this).attr('data-name'))
wn.call({
module: "core",
page: "permission_manager",
method: "update_match",
args: {
name: perm.name,
doctype: perm.parent,
match: match_value
},
callback: function() {
dialog.hide();
me.refresh();
}
})
});
dialog.show();
// select
if(perm.match) {
$(dialog.wrapper).find("[value='"+perm.match+"']").attr("checked", "checked").focus();
} else {
$(dialog.wrapper).find('[value=""]').attr("checked", "checked").focus();
}
});
},
get_profile_fields: function(doctype) {
var profile_fields = wn.model.get("DocField", {parent:doctype,
fieldtype:"Link", options:"Profile"});
profile_fields = profile_fields.concat(wn.model.get("DocField", {parent:doctype,
fieldtype:"Select", link_doctype:"Profile"}))
return profile_fields
},
get_link_fields: function(doctype) {
return link_fields = wn.model.get("DocField", {parent:doctype,
fieldtype:"Link", options:["not in", ["Profile", '[Select]']]});
},
show_explain: function() {
$(".perm-explain").remove();
if(!this.get_doctype()) return;
var wrapper = $("<div class='perm-explain well'></div>").appendTo(this.body);
var doctype = null;
var core_finished = false;
$.each(this.perm_list, function(i, p) {
if(p.parent != doctype) {
core_finished = false;
doctype = p.parent;
$('<h3>For ' + doctype + '</h3><h4>Document Permissions</h4>')
.appendTo(wrapper);
}
if(p.permlevel==0) {
var perms = $.map(["read", "write", "create", "submit", "cancel", "amend"], function(type) {
if(p[type]) return type;
}).join(", ");
if(!p.match) {
var _p = $('<p>').html("A user with role <b>"+p.role + "</b> can "
+ perms + " a document of type <b>" + doctype + "</b>.")
} else {
if(p.match=="owner") {
var _p = $('<p>').html("A user with role <b>"+p.role + "</b> can "
+ perms + " <b>" + doctype + "</b> <u>only if</u> that document is created by that user.");
} else if(p.match.indexOf(":")!=-1) {
var field = p.match.split(":")[0];
var _p = $('<p>').html("A user with role <b>"+p.role + "</b> can "
+ perms + " <b>" + doctype + "</b> <u>only if</u> <b>"+field+"</b> equals User's Id.");
} else {
var _p = $('<p>').html("A user with role <b>"+p.role + "</b> can "
+ perms + " <b>" + doctype + "</b> <u>only for</u> records with user's <b>"+p.match+"</b> property.");
}
}
} else {
if(!core_finished) {
core_finished = true;
$("<br><h4>Field Level Permissions</h4>").appendTo(wrapper);
}
var perms = $.map(["read", "write"], function(type) {
if(p[type]) return type;
}).join(", ");
var _p = $('<p>').html("A user with role <b>"+p.role + "</b> can only <u>"
+ perms + "</u> fields at level <b>"+ p.permlevel +"</b> in a <b>" + doctype + "</b>.")
}
$("<a>Show Users</a>").appendTo(_p).attr("data-role", p.role)
.css("margin-left", "7px")
.click(function() {
var link = $(this);
wn.call({
module: "core",
page: "permission_manager",
method: "get_users_with_role",
args: {
role: link.attr("data-role"),
},
callback: function(r) {
$.each(r.message, function(i, uid) {
msgprint("<a href='#Form/Profile/"+uid+"'>"
+ wn.user_info(uid).fullname + "</a> ("+
uid+")");
});
cur_dialog.set_title("Users with role "
+ link.attr("data-role"));
}
});
});
_p.appendTo(wrapper);
})
}
})

View file

@ -0,0 +1,72 @@
from __future__ import unicode_literals
import webnotes
@webnotes.whitelist(allow_roles=["System Manager", "Administrator"])
def get_roles_and_doctypes():
return {
"doctypes": [d[0] for d in webnotes.conn.sql("""select name from tabDocType where
ifnull(istable,0)=0 and
ifnull(issingle,0)=0 and
module != 'Core' """)],
"roles": [d[0] for d in webnotes.conn.sql("""select name from tabRole where name not in
('All', 'Guest', 'Administrator')""")]
}
@webnotes.whitelist(allow_roles=["System Manager", "Administrator"])
def get_permissions(doctype=None, role=None):
return webnotes.conn.sql("""select * from tabDocPerm
where %s%s order by parent, permlevel, role""" % (\
doctype and (" parent='%s'" % doctype) or "",
role and ((doctype and " and " or "") + " role='%s'" % role) or "",
), as_dict=True)
@webnotes.whitelist(allow_roles=["System Manager", "Administrator"])
def remove(doctype, name):
webnotes.conn.sql("""delete from tabDocPerm where name=%s""", name)
validate_and_reset(doctype, for_remove=True)
@webnotes.whitelist(allow_roles=["System Manager", "Administrator"])
def add(parent, role, permlevel):
webnotes.doc(fielddata={
"doctype":"DocPerm",
"__islocal": 1,
"parent": parent,
"parenttype": "DocType",
"parentfield": "permissions",
"role": role,
"permlevel": permlevel,
"read": 1
}).save()
validate_and_reset(parent)
@webnotes.whitelist(allow_roles=["System Manager", "Administrator"])
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(allow_roles=["System Manager", "Administrator"])
def update_match(name, doctype, match=""):
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 core.doctype.doctype.doctype import validate_permissions_for_doctype
validate_permissions_for_doctype(doctype, for_remove)
webnotes.clear_cache(doctype=doctype)
@webnotes.whitelist(allow_roles=["System Manager", "Administrator"])
def reset(doctype):
webnotes.reset_perms(doctype)
webnotes.clear_cache(doctype=doctype)
@webnotes.whitelist(allow_roles=["System Manager", "Administrator"])
def get_users_with_role(role):
return [p[0] for p in webnotes.conn.sql("""select distinct tabProfile.name
from tabUserRole, tabProfile where
tabUserRole.role=%s
and tabProfile.name != "Administrator"
and tabUserRole.parent = tabProfile.name
and ifnull(tabProfile.enabled,0)=1""", role)]

View file

@ -0,0 +1,21 @@
[
{
"owner": "Administrator",
"docstatus": 0,
"creation": "2013-01-01 11:00:01",
"modified_by": "Administrator",
"modified": "2013-01-01 11:00:01"
},
{
"name": "__common__",
"title": "Permission Manager",
"doctype": "Page",
"module": "Core",
"standard": "Yes",
"page_name": "Permission Manager"
},
{
"name": "permission-manager",
"doctype": "Page"
}
]

View file

View file

@ -0,0 +1,213 @@
wn.pages['user-properties'].onload = function(wrapper) {
wn.ui.make_app_page({
parent: wrapper,
title: 'User Properties',
single_column: true
});
wrapper.user_properties = new wn.UserProperties(wrapper);
}
wn.pages['user-properties'].refresh = function(wrapper) {
wrapper.user_properties.set_from_route();
}
wn.UserProperties = Class.extend({
init: function(wrapper) {
this.wrapper = wrapper;
this.body = $(this.wrapper).find(".layout-main");
this.make();
this.refresh();
},
make: function() {
var me = this;
wn.call({
module:"core",
page:"user_properties",
method: "get_users_and_links",
callback: function(r) {
me.options = r.message;
me.user_select =
me.wrapper.appframe.add_select("users",
["Select User..."].concat(r.message.users))
.css("width", "200px")
.change(function() {
wn.set_route("user-properties", $(this).val())
});
me.property_select =
me.wrapper.appframe.add_select("links",
["Select Property..."].concat(me.get_link_names()))
.css("width", "200px")
.change(function() {
me.refresh();
});
me.set_from_route();
}
});
},
get_link_names: function() {
return $.map(this.options.link_fields, function(l) { return l[0]; });
},
set_from_route: function() {
if(wn.get_route()[1] && this.user_select) {
this.user_select.val(wn.get_route()[1]);
this.refresh();
} else {
this.refresh();
}
},
get_user: function() {
var user = this.user_select.val();
return user=="Select User..." ? null : user;
},
get_property: function() {
var property = this.property_select.val();
return property=="Select Property..." ? null : property;
},
render: function(prop_list) {
this.body.empty();
this.prop_list = prop_list;
if(!prop_list.length) {
this.body.html("<div class='alert'>No User Properties found.</div>");
} else {
this.show_property_table();
}
this.show_add_property();
$("<div class='well'>User Properties appear as default values in forms.\
<br>They are also used to restrict permissions \
in the <a href='#permission-manager'>Permission Manager</a>\
<br>You can also set multiple values for one property. \
If so, the permission rules will apply if any of the values match.</div>").appendTo(this.body);
},
refresh: function() {
var me = this;
if(!me.user_select) {
this.body.html("<div class='alert'>Loading...</div>");
return;
}
if(!me.get_user() && !me.get_property()) {
this.body.html("<div class='alert'>Select User or Property to start.</div>");
return;
}
// get permissions
wn.call({
module: "core",
page: "user_properties",
method: "get_properties",
args: {
user: me.get_user(),
key: me.get_property()
},
callback: function(r) {
me.render(r.message);
}
});
},
show_property_table: function() {
var me = this;
this.table = $("<table class='table table-bordered'>\
<thead><tr></tr></thead>\
<tbody></tbody>\
</table>").appendTo(this.body);
$.each([["User", 150], ["Property", 150], ["Value",150], ["", 50]],
function(i, col) {
$("<th>").html(col[0]).css("width", col[1]+"px")
.appendTo(me.table.find("thead tr"));
});
$.each(this.prop_list, function(i, d) {
var row = $("<tr>").appendTo(me.table.find("tbody"));
$("<td>").html(d.parent).appendTo(row);
$("<td>").html(d.defkey).appendTo(row);
$("<td>").html(d.defvalue).appendTo(row);
me.add_delete_button(row, d);
});
},
add_delete_button: function(row, d) {
var me = this;
$("<button class='btn btn-small'><i class='icon-remove'></i></button>")
.appendTo($("<td>").appendTo(row))
.attr("data-name", d.name)
.attr("data-user", d.parent)
.click(function() {
wn.call({
module: "core",
page: "user_properties",
method: "remove",
args: {
name: $(this).attr("data-name"),
user: $(this).attr("data-user")
},
callback: function(r) {
if(r.exc) {
msgprint("Did not remove.");
} else {
me.refresh();
}
}
})
});
},
show_add_property: function() {
var me = this;
$("<button class='btn btn-info'>Add A Property</button>")
.appendTo($("<p>").appendTo(this.body))
.click(function() {
var d = new wn.ui.Dialog({
title: "Add New Property",
fields: [
{fieldtype:"Select", label:"User",
options:me.options.users, reqd:1, fieldname:"parent"},
{fieldtype:"Select", label:"Property", fieldname:"defkey",
options:me.get_link_names(), reqd:1},
{fieldtype:"Link", label:"Value", fieldname:"defvalue",
options:'[Select]', reqd:1},
{fieldtype:"Button", label:"Add"},
]
});
if(me.get_user()) {
d.set_value("parent", me.get_user());
d.get_input("parent").attr("disabled", true);
}
if(me.get_property()) {
d.set_value("defkey", me.get_property());
d.get_input("defkey").attr("disabled", true);
}
d.fields_dict["defvalue"].get_query = function(txt) {
var key = d.get_value("defkey");
var doctype = $.map(me.options.link_fields, function(l) {
if(l[0]==key) return l[1];
})[0];
return 'select name from `tab'+doctype
+'` where name like "%s"'
}
d.get_input("add").click(function() {
var args = d.get_values();
if(!args) {
return;
}
wn.call({
module: "core",
page: "user_properties",
method: "add",
args: args,
callback: function(r) {
if(r.exc) {
msgprint("Did not add.");
} else {
me.refresh();
}
}
})
d.hide();
});
d.show();
});
}
})

View file

@ -0,0 +1,36 @@
from __future__ import unicode_literals
import webnotes
@webnotes.whitelist(allow_roles=["System Manager", "Administrator"])
def get_users_and_links():
links = list(set(webnotes.conn.sql("""select fieldname, options
from tabDocField where fieldtype='Link'
and parent not in ('[Select]', 'DocType', 'Module Def')
""") + webnotes.conn.sql("""select fieldname, options
from `tabCustom Field` where fieldtype='Link'""")))
links.sort()
return {
"users": [d[0] for d in webnotes.conn.sql("""select name from tabProfile where
ifnull(enabled,0)=1 and
name not in ("Administrator", "Guest")""")],
"link_fields": links
}
@webnotes.whitelist(allow_roles=["System Manager", "Administrator"])
def get_properties(user=None, key=None):
return webnotes.conn.sql("""select name, parent, defkey, defvalue
from tabDefaultValue
where %s%s and parent!='Control Panel' order by parent, defkey""" % (\
user and (" parent='%s'" % user) or "",
key and ((user and " and " or "") + " defkey='%s'" % key) or "",
), as_dict=True)
@webnotes.whitelist(allow_roles=["System Manager", "Administrator"])
def remove(user, name):
webnotes.conn.sql("""delete from tabDefaultValue where name=%s""", name)
webnotes.clear_cache(user=user)
@webnotes.whitelist(allow_roles=["System Manager", "Administrator"])
def add(parent, defkey, defvalue):
webnotes.conn.add_default(defkey, defvalue, parent)

View file

@ -0,0 +1,21 @@
[
{
"owner": "Administrator",
"docstatus": 0,
"creation": "2013-01-01 18:50:55",
"modified_by": "Administrator",
"modified": "2013-01-01 18:50:55"
},
{
"name": "__common__",
"title": "User Properties",
"doctype": "Page",
"module": "Core",
"standard": "Yes",
"page_name": "user-properties"
},
{
"name": "user-properties",
"doctype": "Page"
}
]

View file

@ -86,6 +86,11 @@ $(window).bind('hashchange', function() {
wn.route_titles[wn._cur_route] = document.title;
if(window.location.hash==wn._cur_route)
return;
return;
// hide open dialog
if(cur_dialog)
cur_dialog.hide();
wn.route();
});

View file

@ -113,5 +113,8 @@ wn.ui.FieldGroup = Class.extend({
f.set_input(f.df['default'] || '');
}
}
},
get_input: function(fieldname) {
return $(this.fields_dict[fieldname].input);
}
});

View file

@ -331,19 +331,23 @@ class Database:
if self.sql("""select defkey from `tabDefaultValue` where
defkey=%s and parent=%s """, (key, parent)):
# update
self.sql("""update `tabDefaultValue` set defvalue=%s
where parent=%s and defkey=%s""", (val, parent, key))
webnotes.clear_cache()
else:
from webnotes.model.doc import Document
d = Document('DefaultValue')
d.parent = parent
d.parenttype = 'Control Panel' # does not matter
d.parentfield = 'system_defaults'
d.defkey = key
d.defvalue = val
d.save(1)
self.add_default(key, val, parent)
def add_default(self, key, val, parent="Control Panel"):
d = webnotes.doc('DefaultValue')
d.parent = parent
d.parenttype = 'Control Panel' # does not matter
d.parentfield = 'system_defaults'
d.defkey = key
d.defvalue = val
d.save(1)
webnotes.clear_cache()
def get_default(self, key, parent="Control Panel"):
"""get default value"""

View file

@ -291,6 +291,7 @@ def expand_selects(doclist):
for d in filter(lambda d: d.fieldtype=='Select' \
and (d.options or '').startswith('link:'), doclist):
doctype = d.options.split("\n")[0][5:]
d.link_doctype = doctype
d.options = '\n'.join([''] + [o.name for o in webnotes.conn.sql("""select
name from `tab%s` where docstatus<2 order by name asc""" % doctype, as_dict=1)])