Commit c6297f86 authored by Anand Doshi's avatar Anand Doshi
Browse files

Merge branch 'develop'

parents 027664a0 325a9e0e
develop v11.1.5 v11.1.4 v11.1.3 v11.1.2 v11.1.1 v11.1.0 v11.0.3 v11.0.3-beta.51 v11.0.3-beta.50 v11.0.3-beta.49 v11.0.3-beta.48 v11.0.3-beta.47 v11.0.3-beta.46 v11.0.3-beta.45 v11.0.3-beta.44 v11.0.3-beta.43 v11.0.3-beta.42 v11.0.3-beta.41 v11.0.3-beta.40 v11.0.3-beta.39 v11.0.3-beta.38 v11.0.3-beta.37 v11.0.3-beta.36 v11.0.3-beta.35 v11.0.3-beta.34 v11.0.3-beta.33 v11.0.3-beta.32 v11.0.3-beta.31 v11.0.3-beta.30 v11.0.3-beta.29 v11.0.3-beta.28 v11.0.3-beta.27 v11.0.3-beta.26 v11.0.3-beta.25 v11.0.3-beta.24 v11.0.3-beta.23 v11.0.3-beta.22 v11.0.3-beta.21 v11.0.3-beta.20 v11.0.3-beta.19 v11.0.3-beta.18 v11.0.3-beta.17 v11.0.3-beta.16 v11.0.3-beta.15 v11.0.3-beta.14 v11.0.3-beta.13 v11.0.3-beta.12 v11.0.3-beta.11 v11.0.3-beta.10 v11.0.3-beta.9 v11.0.3-beta.8 v11.0.3-beta.7 v11.0.3-beta.6 v11.0.3-beta.5 v11.0.3-beta.4 v11.0.3-beta.3 v11.0.3-beta.2 v11.0.3-beta.1 v11.0.2 v11.0.1 v11.0.0-beta v10.1.71 v10.1.70 v10.1.69 v10.1.68 v10.1.67 v10.1.66 v10.1.65 v10.1.64 v10.1.63 v10.1.62 v10.1.61 v10.1.60 v10.1.59 v10.1.58 v10.1.57 v10.1.56 v10.1.55 v10.1.54 v10.1.53 v10.1.52 v10.1.51 v10.1.50 v10.1.49 v10.1.49-beta.1 v10.1.48 v10.1.47 v10.1.46 v10.1.45 v10.1.44 v10.1.43 v10.1.42 v10.1.41 v10.1.40 v10.1.39 v10.1.38 v10.1.37 v10.1.36 v10.1.35 v10.1.34 v10.1.33 v10.1.32 v10.1.31 v10.1.30 v10.1.29 v10.1.28 v10.1.27 v10.1.26 v10.1.25 v10.1.24 v10.1.23 v10.1.22 v10.1.21 v10.1.20 v10.1.19 v10.1.18 v10.1.17 v10.1.16 v10.1.15 v10.1.14 v10.1.13 v10.1.12 v10.1.11 v10.1.10 v10.1.9 v10.1.8 v10.1.7 v10.1.6 v10.1.5 v10.1.4 v10.1.3 v10.1.2 v10.1.1 v10.1.0 v10.0.25 v10.0.24 v10.0.23 v10.0.22 v10.0.21 v10.0.20 v10.0.19 v10.0.18 v10.0.17 v10.0.16 v10.0.15 v10.0.14 v10.0.13 v10.0.12 v10.0.11 v10.0.10 v10.0.9 v10.0.8 v10.0.7 v10.0.6 v10.0.5 v10.0.4 v10.0.3 v10.0.2 v10.0.1 v10.0.0 v9.2.25 v9.2.24 v9.2.23 v9.2.22 v9.2.21 v9.2.20 v9.2.19 v9.2.18 v9.2.17 v9.2.16 v9.2.15 v9.2.14 v9.2.13 v9.2.12 v9.2.11 v9.2.10 v9.2.9 v9.2.8 v9.2.7 v9.2.6 v9.2.5 v9.2.4 v9.2.3 v9.2.2 v9.2.1 v9.2.0 v9.1.11 v9.1.10 v9.1.9 v9.1.8 v9.1.7 v9.1.6 v9.1.5 v9.1.4 v9.1.3 v9.1.2 v9.1.1 v9.1.0 v9.0.10 v9.0.9 v9.0.8 v9.0.7 v9.0.6 v9.0.5 v9.0.4 v9.0.3 v9.0.2 v9.0.1 v9.0.0 v8.10.9 v8.10.8 v8.10.7 v8.10.6 v8.10.5 v8.10.4 v8.10.3 v8.10.2 v8.10.1 v8.10.0 v8.9.4 v8.9.3 v8.9.2 v8.9.1 v8.9.0 v8.8.5 v8.8.4 v8.8.3 v8.8.2 v8.8.1 v8.8.0 v8.7.11 v8.7.10 v8.7.9 v8.7.8 v8.7.7 v8.7.6 v8.7.5 v8.7.4 v8.7.3 v8.7.2 v8.7.1 v8.7.0 v8.6.8 v8.6.7 v8.6.6 v8.6.5 v8.6.4 v8.6.3 v8.6.2 v8.6.1 v8.6.0 v8.5.8 v8.5.7 v8.5.6 v8.5.5 v8.5.4 v8.5.3 v8.5.2 v8.5.1 v8.5.0 v8.4.1 v8.4.0 v8.3.10 v8.3.9 v8.3.8 v8.3.7 v8.3.6 v8.3.5 v8.3.4 v8.3.3 v8.3.2 v8.3.1 v8.3.0 v8.2.7 v8.2.6 v8.2.5 v8.2.4 v8.2.3 v8.2.2 v8.2.1 v8.2.0 v8.1.4 v8.1.3 v8.1.2 v8.1.1 v8.1.0 v8.0.71 v8.0.70 v8.0.69 v8.0.68 v8.0.67 v8.0.66 v8.0.65 v8.0.64 v8.0.63 v8.0.62 v8.0.61 v8.0.60 v8.0.59 v8.0.58 v8.0.57 v8.0.56 v8.0.55 v8.0.54 v8.0.53 v8.0.52 v8.0.51 v8.0.50 v8.0.49 v8.0.48 v8.0.47 v8.0.46 v8.0.45 v8.0.44 v8.0.43 v8.0.42 v8.0.41 v8.0.40 v8.0.39 v8.0.38 v8.0.37 v8.0.36 v8.0.35 v8.0.34 v8.0.33 v8.0.32 v8.0.31 v8.0.30 v8.0.29 v8.0.28 v8.0.27 v8.0.26 v8.0.25 v8.0.24 v8.0.23 v8.0.22 v8.0.21 v8.0.20 v8.0.19 v8.0.18 v8.0.17 v8.0.16 v8.0.15 v8.0.14 v8.0.13 v8.0.12 v8.0.11 v8.0.10 v8.0.9 v8.0.8 v8.0.7 v8.0.6 v8.0.5 v8.0.4 v8.0.3 v8.0.2 v8.0.1 v8.0.0 v7.2.31 v7.2.30 v7.2.29 v7.2.28 v7.2.27 v7.2.26 v7.2.25 v7.2.24 v7.2.23 v7.2.22 v7.2.21 v7.2.20 v7.2.19 v7.2.18 v7.2.17 v7.2.16 v7.2.15 v7.2.14 v7.2.13 v7.2.12 v7.2.11 v7.2.10 v7.2.9 v7.2.8 v7.2.7 v7.2.6 v7.2.5 v7.2.4 v7.2.3 v7.2.2 v7.2.1 v7.2.0 v7.1.29 v7.1.28 v7.1.27 v7.1.26 v7.1.25 v7.1.24 v7.1.23 v7.1.22 v7.1.21 v7.1.20 v7.1.19 v7.1.18 v7.1.17 v7.1.16 v7.1.15 v7.1.14 v7.1.13 v7.1.12 v7.1.11 v7.1.10 v7.1.9 v7.1.8 v7.1.7 v7.1.6 v7.1.5 v7.1.4 v7.1.3 v7.1.2 v7.1.1 v7.1.0 v7.0.47 v7.0.46 v7.0.45 v7.0.44 v7.0.43 v7.0.42 v7.0.41 v7.0.40 v7.0.39 v7.0.38 v7.0.37 v7.0.36 v7.0.35 v7.0.34 v7.0.33 v7.0.32 v7.0.31 v7.0.30 v7.0.29 v7.0.28 v7.0.27 v7.0.26 v7.0.25 v7.0.24 v7.0.23 v7.0.22 v7.0.21 v7.0.20 v7.0.19 v7.0.18 v7.0.17 v7.0.16 v7.0.15 v7.0.14 v7.0.13 v7.0.12 v7.0.11 v7.0.10 v7.0.9 v7.0.8 v7.0.7 v7.0.6 v7.0.5 v7.0.4 v7.0.3 v7.0.2 v7.0.1 v7.0.0 v6.27.24 v6.27.23 v6.27.22 v6.27.21 v6.27.20 v6.27.19 v6.27.18 v6.27.17 v6.27.16 v6.27.15 v6.27.14 v6.27.13 v6.27.12 v6.27.11 v6.27.10 v6.27.9 v6.27.8 v6.27.7 v6.27.6 v6.27.5 v6.27.4 v6.27.3 v6.27.2 v6.27.1 v6.27.0 v6.26.6 v6.26.5 v6.26.4 v6.26.3 v6.26.2 v6.26.1 v6.26.0 v6.25.6 v6.25.5 v6.25.4 v6.25.3 v6.25.2 v6.25.1 v6.25.0 v6.24.10 v6.24.9 v6.24.8 v6.24.7 v6.24.6 v6.24.5 v6.24.4 v6.24.3 v6.24.2 v6.24.1 v6.24.0 v6.23.3 v6.23.2 v6.23.1 v6.23.0 v6.22.7 v6.22.6 v6.22.5 v6.22.4 v6.22.3 v6.22.2 v6.22.1 v6.22.0 v6.21.0 v6.20.2 v6.20.1 v6.20.0 v6.19.3 v6.19.2 v6.19.1 v6.19.0 v6.18.1 v6.18.0 v6.17.6 v6.17.5 v6.17.4 v6.17.3 v6.17.2 v6.17.1 v6.17.0 v6.16.4 v6.16.3 v6.16.2 v6.16.1 v6.16.0 v6.15.4 v6.15.3 v6.15.2 v6.15.1 v6.15.0 v6.14.1 v6.14.0 v6.13.5 v6.13.4 v6.13.3 v6.13.2 v6.13.1 v6.13.0 v6.12.4 v6.12.3 v6.12.2 v6.12.1 v6.12.0 v6.11.0 v6.10.4 v6.10.3 v6.10.2 v6.10.1 v6.10.0 v6.9.3 v6.9.2 v6.9.1 v6.9.0 v6.8.2 v6.8.1 v6.8.0 v6.7.11 v6.7.10 v6.7.9 v6.7.8 v6.7.7 v6.7.6 v6.7.5 v6.7.4 v6.7.3 v6.7.2 v6.7.1 v6.7.0 v6.6.5 v6.6.4 v6.6.3 v6.6.2 v6.6.1 v6.6.0 v6.5.4 v6.5.3 v6.5.2 v6.5.1 v6.5.0 v6.4.9 v6.4.8 v6.4.7 v6.4.6 v6.4.5 v6.4.4 v6.4.3 v6.4.2 v6.4.1 v6.4.0 v6.3.0 v6.2.0 v6.1.2 v6.1.1 v6.1.0 v6.0.8 v6.0.7 v6.0.6 v6.0.5 v6.0.4 v6.0.3 v6.0.2 v6.0.1 v6.0.0 v5.4.2 v5.4.1 v5.4.0 v5.3.1 v5.3.0 v5.2.2 v5.2.1 v5.2.0 v5.1.5 v5.1.4 v5.1.3 v5.1.2 v5.1.1
No related merge requests found
Showing with 76 additions and 45 deletions
+76 -45
from __future__ import unicode_literals
__version__ = "5.1.0"
__version__ = "5.1.1"
......@@ -70,6 +70,7 @@ def application(request):
except Exception, e:
http_status_code = getattr(e, "http_status_code", 500)
#print frappe.get_traceback()
if (http_status_code==500
and isinstance(e, MySQLdb.OperationalError)
......
......@@ -82,8 +82,13 @@ class LoginManager:
if frappe.local.form_dict.get('cmd')=='login' or frappe.local.request.path=="/api/method/login":
self.login()
else:
self.make_session(resume=True)
self.set_user_info(resume=True)
try:
self.make_session(resume=True)
self.set_user_info(resume=True)
except AttributeError:
self.user = "Guest"
self.make_session()
self.set_user_info()
def login(self):
# clear cache
......@@ -104,7 +109,8 @@ class LoginManager:
self.info = frappe.db.get_value("User", self.user,
["user_type", "first_name", "last_name", "user_image"], as_dict=1)
self.full_name = " ".join(filter(None, [self.info.first_name, self.info.last_name]))
self.full_name = " ".join(filter(None, [self.info.first_name,
self.info.last_name]))
self.user_type = self.info.user_type
if self.info.user_type=="Website User":
......
- 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):
......
......@@ -388,6 +388,7 @@
{
"allow_on_submit": 0,
"depends_on": "enable_auto_reply",
"description": "ProTip: Add <code>Reference: {{ reference_doctype }} {{ reference_name }}</code> to send document reference",
"fieldname": "auto_reply_message",
"fieldtype": "Text Editor",
"hidden": 0,
......@@ -428,7 +429,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 0,
"modified": "2015-06-11 00:16:24.026081",
"modified": "2015-07-16 10:11:06.466258",
"modified_by": "Administrator",
"module": "Email",
"name": "Email Account",
......
......@@ -5,8 +5,9 @@ from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.model.document import Document
from frappe.utils import validate_email_add, cint, get_datetime, DATE_FORMAT, strip
from frappe.utils import validate_email_add, cint, get_datetime, DATE_FORMAT, strip, comma_or
from frappe.utils.user import is_system_user
from frappe.utils.jinja import render_template
from frappe.email.smtp import SMTPServer
from frappe.email.receive import POP3Server, Email
from poplib import error_proto
......@@ -54,6 +55,11 @@ class EmailAccount(Document):
for e in self.get_unreplied_notification_emails():
validate_email_add(e, True)
if self.enable_incoming and self.append_to:
valid_doctypes = [d[0] for d in get_append_to()]
if self.append_to not in valid_doctypes:
frappe.throw(_("Append To can be one of {0}").format(comma_or(valid_doctypes)))
def on_update(self):
"""Check there is only one default of each type."""
self.there_must_be_only_one_default()
......@@ -182,10 +188,11 @@ class EmailAccount(Document):
sender_field = None
if in_reply_to:
if "@" in in_reply_to:
if "@{0}".format(frappe.local.site) in in_reply_to:
# reply to a communication sent from the system
in_reply_to = in_reply_to.split("@", 1)[0]
in_reply_to, domain = in_reply_to.split("@", 1)
if frappe.db.exists("Communication", in_reply_to):
parent = frappe.get_doc("Communication", in_reply_to)
......@@ -241,6 +248,7 @@ class EmailAccount(Document):
else:
parent = None
# NOTE if parent isn't found and there's no subject match, it is likely that it is a new conversation thread and hence is_first = True
communication.is_first = True
if parent:
......@@ -249,14 +257,14 @@ class EmailAccount(Document):
def send_auto_reply(self, communication, email):
"""Send auto reply if set."""
if self.auto_reply_message:
if self.enable_auto_reply:
communication.set_incoming_outgoing_accounts()
frappe.sendmail(recipients = [email.from_email],
sender = self.email_id,
reply_to = communication.incoming_email_account,
subject = _("Re: ") + communication.subject,
content = self.auto_reply_message or \
content = render_template(self.auto_reply_message or "", communication.as_dict()) or \
frappe.get_template("templates/emails/auto_reply.html").render(communication.as_dict()),
reference_doctype = communication.reference_doctype,
reference_name = communication.reference_name,
......@@ -275,7 +283,7 @@ class EmailAccount(Document):
frappe.db.sql("update `tabCommunication` set email_account='' where email_account=%s", self.name)
@frappe.whitelist()
def get_append_to(doctype, txt, searchfield, start, page_len, filters):
def get_append_to(doctype=None, txt=None, searchfield=None, start=None, page_len=None, filters=None):
if not txt: txt = ""
return [[d] for d in frappe.get_hooks("email_append_to") if txt in d]
......
......@@ -4,7 +4,7 @@ app_title = "Frappe Framework"
app_publisher = "Frappe Technologies Pvt. Ltd."
app_description = "Full Stack Web Application Framework in Python"
app_icon = "octicon octicon-circuit-board"
app_version = "5.1.0"
app_version = "5.1.1"
app_color = "orange"
app_email = "support@frappe.io"
......
......@@ -261,7 +261,7 @@ class BaseDocument(object):
return
type, value, traceback = sys.exc_info()
frappe.msgprint(_("Duplicate name {0} {1}").format(self.doctype, self.name))
raise frappe.NameError, (self.doctype, self.name, e), traceback
raise frappe.DuplicateEntryError, (self.doctype, self.name, e), traceback
else:
raise
......
......@@ -270,7 +270,6 @@ class DatabaseQuery(object):
"""add match conditions if applicable"""
self.match_filters = []
self.match_conditions = []
only_if_shared = False
if not self.tables: self.extract_tables()
......@@ -295,10 +294,6 @@ class DatabaseQuery(object):
self.add_user_permissions(user_permissions,
user_permission_doctypes=role_permissions.get("user_permission_doctypes").get("read"))
# share is an OR condition, if there is a role permission
if not only_if_shared and self.shared:
self.match_conditions.append(self.get_share_condition())
if as_condition:
conditions = ""
if self.match_conditions:
......@@ -309,6 +304,14 @@ class DatabaseQuery(object):
if doctype_conditions:
conditions += (' and ' + doctype_conditions) if conditions else doctype_conditions
# share is an OR condition, if there is a role permission
if not only_if_shared and self.shared:
if conditions:
conditions = "({conditions}) or ({shared_condition})".format(
conditions=conditions, shared_condition=self.get_share_condition())
else:
conditions = "{shared_condition}".format(shared_condition=self.get_share_condition())
return conditions
else:
......
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# MIT License. See license.txt
from __future__ import unicode_literals
import frappe, json
from frappe import _
"""
Model utilities, unclassified functions
"""
def set_default(doc, key):
"""Set is_default property of given doc and unset all others filtered by given key."""
if not doc.is_default:
frappe.db.set(doc, "is_default", 1)
frappe.db.sql("""update `tab%s` set `is_default`=0
where `%s`=%s and name!=%s""" % (doc.doctype, key, "%s", "%s"),
(doc.get(key), doc.name))
......@@ -5,6 +5,7 @@ from __future__ import unicode_literals
import frappe
import json
from frappe.model import no_value_fields
def rename_field(doctype, old_fieldname, new_fieldname):
"""This functions assumes that doctype is already synced"""
......
from __future__ import unicode_literals
import frappe
from frappe.model.utils import rename_field
from frappe.model.utils.rename_field import rename_field
from frappe.model.meta import get_table_columns
def execute():
......
from __future__ import unicode_literals
import frappe
from frappe.model.utils import rename_field
from frappe.model.utils.rename_field import rename_field
def execute():
tables = frappe.db.sql_list("show tables")
......
......@@ -2,7 +2,7 @@
# License: GNU General Public License v3. See license.txt
import frappe
from frappe.model.utils import rename_field
from frappe.model.utils.rename_field import rename_field
from frappe.modules import scrub, get_doctype_module
rename_map = {
......
......@@ -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;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment