[feature] Share with Everyone
This commit is contained in:
parent
d69af7bcfe
commit
d70968dbc5
13 changed files with 150 additions and 48 deletions
1
frappe/change_log/current/share_with_everyone.md
Normal file
1
frappe/change_log/current/share_with_everyone.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
- Ability to **Share with Everyone** (except Guest) using **Share With**
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
"print_hide": 0,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"reqd": 0,
|
||||
"search_index": 1,
|
||||
"set_only_once": 0
|
||||
},
|
||||
|
|
@ -129,6 +129,13 @@
|
|||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "everyone",
|
||||
"fieldtype": "Check",
|
||||
"label": "Everyone",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
}
|
||||
],
|
||||
"hide_heading": 0,
|
||||
|
|
@ -138,7 +145,7 @@
|
|||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"modified": "2015-02-12 11:30:52.968078",
|
||||
"modified": "2015-07-17 07:02:10.632582",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Core",
|
||||
"name": "DocShare",
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ class DocShare(Document):
|
|||
no_feed_on_delete = True
|
||||
|
||||
def validate(self):
|
||||
self.validate_user()
|
||||
self.check_share_permission()
|
||||
self.cascade_permissions_downwards()
|
||||
self.get_doc().run_method("validate_share", self)
|
||||
|
|
@ -26,6 +27,12 @@ class DocShare(Document):
|
|||
self._doc = frappe.get_doc(self.share_doctype, self.share_name)
|
||||
return self._doc
|
||||
|
||||
def validate_user(self):
|
||||
if self.everyone:
|
||||
self.user = None
|
||||
elif not self.user:
|
||||
frappe.throw(_("User is mandatory for Share"), frappe.MandatoryError)
|
||||
|
||||
def check_share_permission(self):
|
||||
if (not self.flags.ignore_share_permission and
|
||||
not frappe.has_permission(self.share_doctype, "share", self.get_doc())):
|
||||
|
|
|
|||
|
|
@ -78,3 +78,15 @@ class TestDocShare(unittest.TestCase):
|
|||
frappe.set_user(self.user)
|
||||
self.assertFalse(self.event.has_permission("share"))
|
||||
|
||||
def test_share_with_everyone(self):
|
||||
self.assertTrue(self.event.name not in frappe.share.get_shared("Event", self.user))
|
||||
|
||||
frappe.share.set_permission("Event", self.event.name, None, "read", everyone=1)
|
||||
self.assertTrue(self.event.name in frappe.share.get_shared("Event", self.user))
|
||||
self.assertTrue(self.event.name in frappe.share.get_shared("Event", "test1@example.com"))
|
||||
self.assertTrue(self.event.name not in frappe.share.get_shared("Event", "Guest"))
|
||||
|
||||
frappe.share.set_permission("Event", self.event.name, None, "read", value=0, everyone=1)
|
||||
self.assertTrue(self.event.name not in frappe.share.get_shared("Event", self.user))
|
||||
self.assertTrue(self.event.name not in frappe.share.get_shared("Event", "test1@example.com"))
|
||||
self.assertTrue(self.event.name not in frappe.share.get_shared("Event", "Guest"))
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ def get_docinfo(doc=None, doctype=None, name=None):
|
|||
"assignments": get_assignments(doc.doctype, doc.name),
|
||||
"permissions": get_doc_permissions(doc),
|
||||
"shared": frappe.share.get_users(doc.doctype, doc.name,
|
||||
fields=["user", "read", "write", "share"])
|
||||
fields=["user", "read", "write", "share", "everyone"])
|
||||
}
|
||||
|
||||
def get_user_permissions(meta):
|
||||
|
|
|
|||
|
|
@ -40,15 +40,16 @@ def has_permission(doctype, ptype="read", doc=None, verbose=False, user=None):
|
|||
|
||||
def false_if_not_shared():
|
||||
if ptype in ("read", "write", "share", "email", "print"):
|
||||
shared = frappe.share.get_shared(doctype, user,
|
||||
["read" if ptype in ("email", "print") else ptype])
|
||||
if doc:
|
||||
doc_name = doc if isinstance(doc, basestring) else doc.name
|
||||
shared = frappe.share.get_shared(doctype, user,
|
||||
["read" if ptype in ("email", "print") else ptype])
|
||||
|
||||
if doc_name in shared:
|
||||
if verbose: print "Shared"
|
||||
if ptype in ("read", "write", "share") or meta.permissions[0].get(ptype):
|
||||
return True
|
||||
|
||||
|
||||
else:
|
||||
if verbose: print "Has a shared document"
|
||||
return True
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
}
|
||||
.avatar-empty {
|
||||
border: 1px dashed #d1d8dd;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.avatar-small {
|
||||
margin-right: 5px;
|
||||
|
|
|
|||
|
|
@ -140,7 +140,7 @@ body[data-route^="Module"] .main-menu .form-sidebar {
|
|||
.form-sidebar .form-shared .share-doc-btn {
|
||||
cursor: pointer;
|
||||
}
|
||||
.form-sidebar .form-shared .octicon-plus {
|
||||
.form-sidebar .form-shared .octicon {
|
||||
position: relative;
|
||||
top: 2px;
|
||||
left: 7px;
|
||||
|
|
@ -148,6 +148,14 @@ body[data-route^="Module"] .main-menu .form-sidebar {
|
|||
.form-sidebar .form-shared .avatar {
|
||||
margin-top: 5px;
|
||||
}
|
||||
.form-sidebar .form-shared .shared-with-everyone {
|
||||
border-style: solid;
|
||||
border-color: #f0f4f7;
|
||||
background-color: #f0f4f7;
|
||||
}
|
||||
.form-sidebar .form-shared .shared-with-everyone .octicon {
|
||||
color: #36414c !important;
|
||||
}
|
||||
.form-sidebar .form-shared .share-doc-btn:hover,
|
||||
.form-sidebar .form-shared .share-doc-btn:focus,
|
||||
.form-sidebar .form-shared .share-doc-btn:active {
|
||||
|
|
|
|||
|
|
@ -1,29 +1,35 @@
|
|||
<div class="padding">
|
||||
|
||||
{% if(!shared.length) { %}
|
||||
<p class="text-muted">{%= __("Not shared with anyone yet.") %}</p>
|
||||
{% } else { %}
|
||||
<div class="row">
|
||||
<div class="col-xs-6"><h6>{%= __("User") %}</h6></div>
|
||||
<div class="col-xs-2"><h6>{%= __("Can Read") %}</h6></div>
|
||||
<div class="col-xs-2"><h6>{%= __("Can Write") %}</h6></div>
|
||||
<div class="col-xs-2"><h6>{%= __("Can Share") %}</h6></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-6"><h6>{%= __("User") %}</h6></div>
|
||||
<div class="col-xs-2"><h6>{%= __("Can Read") %}</h6></div>
|
||||
<div class="col-xs-2"><h6>{%= __("Can Write") %}</h6></div>
|
||||
<div class="col-xs-2"><h6>{%= __("Can Share") %}</h6></div>
|
||||
</div>
|
||||
|
||||
{% for (var i=0, l=shared.length; i < l; i++) {
|
||||
var s = shared[i]; %}
|
||||
{% if(s) { %}
|
||||
<div class="row shared-user" data-user="{%= s.user %}" data-name="{%= s.name %}">
|
||||
<div class="col-xs-6">{%= s.user %}</div>
|
||||
<div class="col-xs-2"><input type="checkbox" name="read"
|
||||
{% if(cint(s.read)) { %}checked{% } %} class="edit-share"></div>
|
||||
<div class="col-xs-2"><input type="checkbox" name="write"
|
||||
{% if(cint(s.write)) { %}checked{% } %} class="edit-share"></div>
|
||||
<div class="col-xs-2"><input type="checkbox" name="share"
|
||||
{% if(cint(s.share)) { %}checked{% } %} class="edit-share"></div>
|
||||
</div>
|
||||
{% } %}
|
||||
{% } %}
|
||||
<div class="row shared-user" data-everyone=1>
|
||||
<div class="col-xs-6 share-all" style="height: 30px;"><b>{{ __("Everyone") }}</b></div>
|
||||
<div class="col-xs-2"><input type="checkbox" name="read"
|
||||
{% if(cint(everyone.read)) { %}checked{% } %} class="edit-share"></div>
|
||||
<div class="col-xs-2"><input type="checkbox" name="write"
|
||||
{% if(cint(everyone.write)) { %}checked{% } %} class="edit-share"></div>
|
||||
<div class="col-xs-2"><input type="checkbox" name="share"
|
||||
{% if(cint(everyone.share)) { %}checked{% } %} class="edit-share"></div>
|
||||
</div>
|
||||
|
||||
{% for (var i=0, l=shared.length; i < l; i++) {
|
||||
var s = shared[i]; %}
|
||||
{% if(s && !s.everyone) { %}
|
||||
<div class="row shared-user" data-user="{%= s.user %}" data-name="{%= s.name %}">
|
||||
<div class="col-xs-6">{%= s.user %}</div>
|
||||
<div class="col-xs-2"><input type="checkbox" name="read"
|
||||
{% if(cint(s.read)) { %}checked{% } %} class="edit-share"></div>
|
||||
<div class="col-xs-2"><input type="checkbox" name="write"
|
||||
{% if(cint(s.write)) { %}checked{% } %} class="edit-share"></div>
|
||||
<div class="col-xs-2"><input type="checkbox" name="share"
|
||||
{% if(cint(s.share)) { %}checked{% } %} class="edit-share"></div>
|
||||
</div>
|
||||
{% } %}
|
||||
{% } %}
|
||||
|
||||
{% if(frappe.model.can_share(null, frm)) { %}
|
||||
|
|
|
|||
|
|
@ -10,26 +10,42 @@ frappe.ui.form.Share = Class.extend({
|
|||
refresh: function() {
|
||||
var me = this;
|
||||
this.parent.empty();
|
||||
|
||||
var everyone = null;
|
||||
var shared = $.map(this.shared || this.frm.get_docinfo().shared, function(s) {
|
||||
if (s.everyone) {
|
||||
everyone = s;
|
||||
}
|
||||
|
||||
return s ? s.user : null;
|
||||
});
|
||||
|
||||
if (everyone) {
|
||||
$(repl('<span><a class="avatar avatar-small avatar-empty share-doc-btn shared-with-everyone" title="%(title)s">\
|
||||
<i class="octicon octicon-megaphone text-muted"></i></a></span>', {title: __("Shared with everyone")}))
|
||||
.appendTo(this.parent)
|
||||
.on("click", function() { me.frm.share_doc(); });
|
||||
}
|
||||
|
||||
for(var i=0; i<shared.length; i++) {
|
||||
var user_info = frappe.user_info(shared[i])
|
||||
var user_info = frappe.user_info(shared[i]);
|
||||
$(repl('<span class="avatar avatar-small" title="'
|
||||
+__("Shared with {0}", [user_info.fullname])+'">\
|
||||
<img class="media-object" src="%(image)s" alt="%(fullname)s"></span>',
|
||||
{image: user_info.image, fullname: user_info.fullname}))
|
||||
.appendTo(this.parent)
|
||||
.on("click", function() { me.frm.share_doc(); });;
|
||||
.on("click", function() { me.frm.share_doc(); });
|
||||
}
|
||||
|
||||
// share
|
||||
if(!me.frm.doc.__islocal) {
|
||||
$(repl('<span><a class="avatar avatar-small avatar-empty share-doc-btn" title="%(title)s">\
|
||||
<i class="octicon octicon-plus text-muted"></i></a></span>', {title: __("Share")}))
|
||||
.appendTo(this.parent)
|
||||
.on("click", function() { me.frm.share_doc(); });
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
show: function() {
|
||||
var me = this;
|
||||
|
|
@ -65,7 +81,16 @@ frappe.ui.form.Share = Class.extend({
|
|||
this.shared = shared;
|
||||
var d = this.dialog;
|
||||
$(d.body).empty();
|
||||
$(frappe.render_template("set_sharing", {frm: this.frm, shared: this.shared}))
|
||||
|
||||
var everyone = {};
|
||||
$.each(this.shared, function(i, s) {
|
||||
// pullout everyone record from shared list
|
||||
if (s && s.everyone) {
|
||||
everyone = s;
|
||||
}
|
||||
});
|
||||
|
||||
$(frappe.render_template("set_sharing", {frm: this.frm, shared: this.shared, everyone: everyone}))
|
||||
.appendTo(d.body);
|
||||
|
||||
if(frappe.model.can_share(null, this.frm)) {
|
||||
|
|
@ -113,6 +138,7 @@ frappe.ui.form.Share = Class.extend({
|
|||
write: $(d.body).find(".add-share-write").prop("checked") ? 1 : 0,
|
||||
share: $(d.body).find(".add-share-share").prop("checked") ? 1 : 0
|
||||
},
|
||||
btn: this,
|
||||
callback: function(r) {
|
||||
$.each(me.shared, function(i, s) {
|
||||
if(s && s.user===r.message.user) {
|
||||
|
|
@ -131,9 +157,10 @@ frappe.ui.form.Share = Class.extend({
|
|||
set_edit_share_events: function() {
|
||||
var me = this, d = this.dialog;
|
||||
$(d.body).find(".edit-share").on("click", function() {
|
||||
var user = $(this).parents(".shared-user:first").attr("data-user"),
|
||||
var user = $(this).parents(".shared-user:first").attr("data-user") || "",
|
||||
value = $(this).prop("checked") ? 1 : 0,
|
||||
property = $(this).attr("name");
|
||||
property = $(this).attr("name")
|
||||
everyone = cint($(this).parents(".shared-user:first").attr("data-everyone"));
|
||||
|
||||
frappe.call({
|
||||
method: "frappe.share.set_permission",
|
||||
|
|
@ -142,20 +169,28 @@ frappe.ui.form.Share = Class.extend({
|
|||
name: me.frm.doc.name,
|
||||
user: user,
|
||||
permission_to: property,
|
||||
value: value
|
||||
value: value,
|
||||
everyone: everyone
|
||||
},
|
||||
callback: function(r) {
|
||||
var found = null;
|
||||
$.each(me.shared, function(i, s) {
|
||||
// update shared object
|
||||
if(s && s.user===user) {
|
||||
if(s && (s.user===user || (everyone && s.everyone===1))) {
|
||||
if(!r.message) {
|
||||
delete me.shared[i];
|
||||
} else {
|
||||
me.shared[i] = $.extend(s, r.message);
|
||||
}
|
||||
found = true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
if (!found) {
|
||||
me.shared.push(r.message);
|
||||
}
|
||||
|
||||
me.dirty = true;
|
||||
me.render_shared();
|
||||
me.frm.shared.refresh();
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
.avatar-empty {
|
||||
border: 1px dashed #d1d8dd;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.avatar-small {
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ body[data-route^="Module"] .main-menu {
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
.octicon-plus {
|
||||
.octicon {
|
||||
position: relative;
|
||||
top: 2px;
|
||||
left: 7px;
|
||||
|
|
@ -129,6 +129,16 @@ body[data-route^="Module"] .main-menu {
|
|||
.avatar {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.shared-with-everyone {
|
||||
border-style: solid;
|
||||
border-color: @btn-bg;
|
||||
background-color: @btn-bg;
|
||||
|
||||
.octicon {
|
||||
color: @text-color !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,13 +6,12 @@ import frappe
|
|||
from frappe.utils import cint
|
||||
|
||||
@frappe.whitelist()
|
||||
def add(doctype, name, user=None, read=1, write=0, share=0, flags=None):
|
||||
def add(doctype, name, user=None, read=1, write=0, share=0, everyone=0, flags=None):
|
||||
"""Share the given document with a user."""
|
||||
if not user:
|
||||
user = frappe.session.user
|
||||
|
||||
share_name = frappe.db.get_value("DocShare", {"user": user, "share_name": name,
|
||||
"share_doctype": doctype})
|
||||
share_name = get_share_name(doctype, name, user, everyone)
|
||||
|
||||
if share_name:
|
||||
doc = frappe.get_doc("DocShare", share_name)
|
||||
|
|
@ -21,7 +20,8 @@ def add(doctype, name, user=None, read=1, write=0, share=0, flags=None):
|
|||
doc.update({
|
||||
"user": user,
|
||||
"share_doctype": doctype,
|
||||
"share_name": name
|
||||
"share_name": name,
|
||||
"everyone": cint(everyone)
|
||||
})
|
||||
|
||||
if flags:
|
||||
|
|
@ -46,14 +46,14 @@ def remove(doctype, name, user, flags=None):
|
|||
frappe.delete_doc("DocShare", share_name)
|
||||
|
||||
@frappe.whitelist()
|
||||
def set_permission(doctype, name, user, permission_to, value=1):
|
||||
def set_permission(doctype, name, user, permission_to, value=1, everyone=0):
|
||||
"""Set share permission."""
|
||||
share_name = frappe.db.get_value("DocShare", {"user": user, "share_name": name,
|
||||
"share_doctype": doctype})
|
||||
share_name = get_share_name(doctype, name, user, everyone)
|
||||
value = int(value)
|
||||
|
||||
if not share_name:
|
||||
if value:
|
||||
share = add(doctype, name, user, **{permission_to: 1})
|
||||
share = add(doctype, name, user, everyone=everyone, **{permission_to: 1})
|
||||
else:
|
||||
# no share found, nothing to remove
|
||||
share = {}
|
||||
|
|
@ -102,7 +102,9 @@ def get_shared(doctype, user=None, rights=None):
|
|||
|
||||
condition = " and ".join(["`{0}`=1".format(right) for right in rights])
|
||||
|
||||
return frappe.db.sql_list("select share_name from tabDocShare where user=%s and share_doctype=%s and {0}".format(condition),
|
||||
return frappe.db.sql_list("""select share_name from tabDocShare
|
||||
where (user=%s {everyone}) and share_doctype=%s and {condition}""".format(
|
||||
condition=condition, everyone="or everyone=1" if user!="Guest" else ""),
|
||||
(user, doctype))
|
||||
|
||||
def get_shared_doctypes(user=None):
|
||||
|
|
@ -110,4 +112,15 @@ def get_shared_doctypes(user=None):
|
|||
if not user:
|
||||
user = frappe.session.user
|
||||
|
||||
return frappe.db.sql_list("select distinct share_doctype from tabDocShare where user=%s", user)
|
||||
return frappe.db.sql_list("select distinct share_doctype from tabDocShare where (user=%s or everyone=1)", user)
|
||||
|
||||
def get_share_name(doctype, name, user, everyone):
|
||||
if cint(everyone):
|
||||
share_name = frappe.db.get_value("DocShare", {"everyone": 1, "share_name": name,
|
||||
"share_doctype": doctype})
|
||||
else:
|
||||
share_name = frappe.db.get_value("DocShare", {"user": user, "share_name": name,
|
||||
"share_doctype": doctype})
|
||||
|
||||
return share_name
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue