diff --git a/frappe/change_log/current/share_with_everyone.md b/frappe/change_log/current/share_with_everyone.md
new file mode 100644
index 0000000000..befa5be85c
--- /dev/null
+++ b/frappe/change_log/current/share_with_everyone.md
@@ -0,0 +1 @@
+- Ability to **Share with Everyone** (except Guest) using **Share With**
diff --git a/frappe/core/doctype/docshare/docshare.json b/frappe/core/doctype/docshare/docshare.json
index 68ebe45c7b..ed649f2930 100644
--- a/frappe/core/doctype/docshare/docshare.json
+++ b/frappe/core/doctype/docshare/docshare.json
@@ -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",
diff --git a/frappe/core/doctype/docshare/docshare.py b/frappe/core/doctype/docshare/docshare.py
index cf79e0531c..5f2b3ae1bd 100644
--- a/frappe/core/doctype/docshare/docshare.py
+++ b/frappe/core/doctype/docshare/docshare.py
@@ -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())):
diff --git a/frappe/core/doctype/docshare/test_docshare.py b/frappe/core/doctype/docshare/test_docshare.py
index 4fb522e267..e4a41ac0d2 100644
--- a/frappe/core/doctype/docshare/test_docshare.py
+++ b/frappe/core/doctype/docshare/test_docshare.py
@@ -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"))
diff --git a/frappe/desk/form/load.py b/frappe/desk/form/load.py
index 2d99fb130e..1cab39bed2 100644
--- a/frappe/desk/form/load.py
+++ b/frappe/desk/form/load.py
@@ -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):
diff --git a/frappe/permissions.py b/frappe/permissions.py
index 690ea63ff8..c3183d2cd0 100644
--- a/frappe/permissions.py
+++ b/frappe/permissions.py
@@ -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
diff --git a/frappe/public/css/avatar.css b/frappe/public/css/avatar.css
index 636cc1baf3..7bc44cacd9 100644
--- a/frappe/public/css/avatar.css
+++ b/frappe/public/css/avatar.css
@@ -12,6 +12,7 @@
}
.avatar-empty {
border: 1px dashed #d1d8dd;
+ border-radius: 4px;
}
.avatar-small {
margin-right: 5px;
diff --git a/frappe/public/css/sidebar.css b/frappe/public/css/sidebar.css
index 9dfe252d58..c9a03858a6 100644
--- a/frappe/public/css/sidebar.css
+++ b/frappe/public/css/sidebar.css
@@ -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 {
diff --git a/frappe/public/js/frappe/form/set_sharing.html b/frappe/public/js/frappe/form/set_sharing.html
index 6088b7a15b..969e0c1461 100644
--- a/frappe/public/js/frappe/form/set_sharing.html
+++ b/frappe/public/js/frappe/form/set_sharing.html
@@ -1,29 +1,35 @@
- {% if(!shared.length) { %}
-
{%= __("Not shared with anyone yet.") %}
- {% } else { %}
-
-
{%= __("User") %}
-
{%= __("Can Read") %}
-
{%= __("Can Write") %}
-
{%= __("Can Share") %}
-
+
+
{%= __("User") %}
+
{%= __("Can Read") %}
+
{%= __("Can Write") %}
+
{%= __("Can Share") %}
+
- {% for (var i=0, l=shared.length; i < l; i++) {
- var s = shared[i]; %}
- {% if(s) { %}
-
- {% } %}
- {% } %}
+
+
{{ __("Everyone") }}
+
+
+
+
+
+ {% for (var i=0, l=shared.length; i < l; i++) {
+ var s = shared[i]; %}
+ {% if(s && !s.everyone) { %}
+
+ {% } %}
{% } %}
{% if(frappe.model.can_share(null, frm)) { %}
diff --git a/frappe/public/js/frappe/form/share.js b/frappe/public/js/frappe/form/share.js
index b15c8086c2..202a884ae5 100644
--- a/frappe/public/js/frappe/form/share.js
+++ b/frappe/public/js/frappe/form/share.js
@@ -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('
\
+ ', {title: __("Shared with everyone")}))
+ .appendTo(this.parent)
+ .on("click", function() { me.frm.share_doc(); });
+ }
+
for(var i=0; i
\
',
{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('\
', {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();
diff --git a/frappe/public/less/avatar.less b/frappe/public/less/avatar.less
index 2fbd3e0ec1..896ab6bc73 100644
--- a/frappe/public/less/avatar.less
+++ b/frappe/public/less/avatar.less
@@ -14,6 +14,7 @@
.avatar-empty {
border: 1px dashed #d1d8dd;
+ border-radius: 4px;
}
.avatar-small {
diff --git a/frappe/public/less/sidebar.less b/frappe/public/less/sidebar.less
index 98bb33a0c6..fde38c0b14 100644
--- a/frappe/public/less/sidebar.less
+++ b/frappe/public/less/sidebar.less
@@ -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;
+ }
+ }
}
}
diff --git a/frappe/share.py b/frappe/share.py
index f6f92535be..a7789468d8 100644
--- a/frappe/share.py
+++ b/frappe/share.py
@@ -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
+