diff --git a/frappe/boot.py b/frappe/boot.py
index f7b817a12e..bb2663cb1c 100644
--- a/frappe/boot.py
+++ b/frappe/boot.py
@@ -54,7 +54,6 @@ def get_bootinfo():
add_allowed_pages(bootinfo)
load_translations(bootinfo)
load_conf_settings(bootinfo)
- load_startup_js(bootinfo)
# ipinfo
if frappe.session['data'].get('ipinfo'):
@@ -120,10 +119,11 @@ def get_fullnames():
return d
-def load_startup_js(bootinfo):
- bootinfo.startup_js = ""
+def get_startup_js():
+ startup_js = []
for method in frappe.get_hooks().startup_js or []:
- bootinfo.startup_js += frappe.get_attr(method)()
+ startup_js.append(frappe.get_attr(method)() or "")
+ return "\n".join(startup_js)
def get_user(bootinfo):
"""get user info"""
diff --git a/frappe/core/doctype/event/event.py b/frappe/core/doctype/event/event.py
index 1c802baf46..aa4312e686 100644
--- a/frappe/core/doctype/event/event.py
+++ b/frappe/core/doctype/event/event.py
@@ -5,6 +5,7 @@ from __future__ import unicode_literals
import frappe
from frappe.utils import getdate, cint, add_months, date_diff, add_days, nowdate
+from frappe.core.doctype.user.user import STANDARD_USERS
weekdays = ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"]
@@ -52,7 +53,9 @@ def send_event_digest():
today = nowdate()
for user in frappe.db.sql("""select name, email, language
from tabUser where ifnull(enabled,0)=1
- and user_type='System User' and name not in ('Guest', 'Administrator')""", as_dict=1):
+ and user_type='System User' and name not in ({})""".format(", ".join(["%s"]*len(STANDARD_USERS))),
+ STANDARD_USERS, as_dict=1):
+
events = get_events(today, today, user.name, for_reminder=True)
if events:
text = ""
diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py
index 5bd3bce4fe..b528640b8f 100644
--- a/frappe/core/doctype/user/user.py
+++ b/frappe/core/doctype/user/user.py
@@ -7,6 +7,8 @@ from frappe.utils import cint, now, cstr
from frappe import throw, msgprint, _
from frappe.auth import _update_password
+STANDARD_USERS = ("Guest", "Administrator")
+
class DocType:
def __init__(self, doc, doclist):
self.doc = doc
@@ -14,7 +16,7 @@ class DocType:
def autoname(self):
"""set name as email id"""
- if self.doc.name not in ('Guest','Administrator'):
+ if self.doc.name not in STANDARD_USERS:
self.doc.email = self.doc.email.strip()
self.doc.name = self.doc.email
@@ -23,31 +25,16 @@ class DocType:
def validate(self):
self.in_insert = self.doc.fields.get("__islocal")
- if self.doc.name not in ('Guest','Administrator'):
+ if self.doc.name not in STANDARD_USERS:
self.validate_email_type(self.doc.email)
- self.validate_max_users()
self.add_system_manager_role()
self.check_enable_disable()
- if self.in_insert:
- if self.doc.name not in ("Guest", "Administrator"):
- if self.doc.new_password:
- # new password given, no email required
- _update_password(self.doc.name, self.doc.new_password)
- if not getattr(self, "no_welcome_mail", False):
- self.send_welcome_mail()
- msgprint(_("Welcome Email Sent"))
- else:
- try:
- self.email_new_password()
- except frappe.OutgoingEmailError:
- pass # email server not set, don't send email
-
self.doc.new_password = ""
self.update_gravatar()
def check_enable_disable(self):
# do not allow disabling administrator/guest
- if not cint(self.doc.enabled) and self.doc.name in ["Administrator", "Guest"]:
+ if not cint(self.doc.enabled) and self.doc.name in STANDARD_USERS:
throw("{msg}: {name}".format(**{
"msg": _("Hey! You cannot disable user"),
"name": self.doc.name
@@ -60,26 +47,6 @@ class DocType:
if not cint(self.doc.enabled) and getattr(frappe, "login_manager", None):
frappe.local.login_manager.logout(user=self.doc.name)
- def validate_max_users(self):
- """don't allow more than max users if set in conf"""
- from frappe import conf
- # check only when enabling a user
- if 'max_users' in conf and self.doc.enabled and \
- self.doc.name not in ["Administrator", "Guest"] and \
- cstr(self.doc.user_type).strip() in ("", "System User"):
- active_users = frappe.db.sql("""select count(*) from tabUser
- where ifnull(enabled, 0)=1 and docstatus<2
- and ifnull(user_type, "System User") = "System User"
- and name not in ('Administrator', 'Guest', %s)""", (self.doc.name,))[0][0]
- if active_users >= conf.max_users and conf.max_users:
- throw("""
- You already have %(active_users)s active users, \
- which is the maximum number that you are currently allowed to add.
\
- So, to add more users, you can:
\
- 1. Upgrade to the unlimited users plan, or
\
- 2. Disable one or more of your existing users and try again""" \
- % {'active_users': active_users})
-
def add_system_manager_role(self):
# if adding system manager, do nothing
if not cint(self.doc.enabled) or ("System Manager" in [user_role.role for user_role in
@@ -107,6 +74,21 @@ class DocType:
frappe.db.set(self.doc, 'owner', self.doc.name)
frappe.clear_cache(user=self.doc.name)
+ try:
+ if self.in_insert:
+ if self.doc.name not in STANDARD_USERS:
+ if self.doc.new_password:
+ # new password given, no email required
+ _update_password(self.doc.name, self.doc.new_password)
+ if not getattr(self, "no_welcome_mail", False):
+ self.send_welcome_mail()
+ msgprint(_("Welcome Email Sent"))
+ else:
+ self.email_new_password()
+
+ except frappe.OutgoingEmailError:
+ pass # email server not set, don't send email
+
def update_gravatar(self):
import md5
if not self.doc.user_image:
@@ -168,7 +150,7 @@ class DocType:
args.update(add_args)
- sender = frappe.session.user not in ("Administrator", "Guest") and frappe.session.user or None
+ sender = frappe.session.user not in STANDARD_USERS and frappe.session.user or None
frappe.sendmail(recipients=self.doc.email, sender=sender, subject=subject,
message=frappe.get_template(template).render(args))
@@ -179,7 +161,7 @@ class DocType:
def on_trash(self):
frappe.clear_cache(user=self.doc.name)
- if self.doc.name in ["Administrator", "Guest"]:
+ if self.doc.name in STANDARD_USERS:
throw("{msg}: {name}".format(**{
"msg": _("Hey! You cannot delete user"),
"name": self.doc.name
@@ -215,7 +197,7 @@ class DocType:
def validate_rename(self, olddn, newdn):
# do not allow renaming administrator and guest
- if olddn in ["Administrator", "Guest"]:
+ if olddn in STANDARD_USERS:
throw("{msg}: {name}".format(**{
"msg": _("Hey! You are restricted from renaming the user"),
"name": olddn
@@ -357,35 +339,50 @@ def reset_password(user):
def user_query(doctype, txt, searchfield, start, page_len, filters):
from frappe.widgets.reportview import get_match_cond
+ txt = "%{}%".format(txt)
return frappe.db.sql("""select name, concat_ws(' ', first_name, middle_name, last_name)
from `tabUser`
where ifnull(enabled, 0)=1
and docstatus < 2
- and name not in ('Administrator', 'Guest')
+ and name not in ({standard_users})
and user_type != 'Website User'
- and (%(key)s like "%(txt)s"
- or concat_ws(' ', first_name, middle_name, last_name) like "%(txt)s")
- %(mcond)s
+ and ({key} like %s
+ or concat_ws(' ', first_name, middle_name, last_name) like %s)
+ {mcond}
order by
- case when name like "%(txt)s" then 0 else 1 end,
- case when concat_ws(' ', first_name, middle_name, last_name) like "%(txt)s"
+ case when name like %s then 0 else 1 end,
+ case when concat_ws(' ', first_name, middle_name, last_name) like %s
then 0 else 1 end,
name asc
- limit %(start)s, %(page_len)s""" % {'key': searchfield, 'txt': "%%%s%%" % txt,
- 'mcond':get_match_cond(doctype), 'start': start, 'page_len': page_len})
+ limit %s, %s""".format(standard_users=", ".join(["%s"]*len(STANDARD_USERS)),
+ key=searchfield, mcond=get_match_cond(doctype)),
+ tuple(list(STANDARD_USERS) + [txt, txt, txt, txt, start, page_len]))
-def get_total_users():
+def get_total_users(exclude_users=None):
"""Returns total no. of system users"""
- return frappe.db.sql("""select count(*) from `tabUser`
- where enabled = 1 and user_type != 'Website User'
- and name not in ('Administrator', 'Guest')""")[0][0]
+ return len(get_system_users(exclude_users=exclude_users))
+
+def get_system_users(exclude_users=None):
+ if not exclude_users:
+ exclude_users = []
+ elif not isinstance(exclude_users, (list, tuple)):
+ exclude_users = [exclude_users]
+
+ exclude_users += list(STANDARD_USERS)
+
+ system_users = frappe.db.sql_list("""select name from `tabUser`
+ where enabled=1 and user_type != 'Website User'
+ and name not in ({})""".format(", ".join(["%s"]*len(exclude_users))),
+ exclude_users)
+
+ return system_users
def get_active_users():
"""Returns No. of system users who logged in, in the last 3 days"""
return frappe.db.sql("""select count(*) from `tabUser`
where enabled = 1 and user_type != 'Website User'
- and name not in ('Administrator', 'Guest')
- and hour(timediff(now(), last_login)) < 72""")[0][0]
+ and name not in ({})
+ and hour(timediff(now(), last_login)) < 72""".format(", ".join(["%s"]*len(STANDARD_USERS))), STANDARD_USERS)[0][0]
def get_website_users():
"""Returns total no. of website users"""
diff --git a/frappe/core/page/messages/messages.py b/frappe/core/page/messages/messages.py
index 0e29cd0697..9c9363915e 100644
--- a/frappe/core/page/messages/messages.py
+++ b/frappe/core/page/messages/messages.py
@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe
from frappe.core.doctype.notification_count.notification_count import delete_notification_count_for
-
+from frappe.core.doctype.user.user import STANDARD_USERS
@frappe.whitelist()
def get_list(arg=None):
@@ -51,8 +51,8 @@ def get_active_users():
from tabUser
where ifnull(enabled,0)=1 and
ifnull(user_type, '')!='Website User' and
- name not in ('Administrator', 'Guest')
- order by first_name""", as_dict=1)
+ name not in ({})
+ order by first_name""".format(", ".join(["%s"]*len(STANDARD_USERS))), STANDARD_USERS, as_dict=1)
@frappe.whitelist()
def post(arg=None):
diff --git a/frappe/core/page/user_properties/user_properties.py b/frappe/core/page/user_properties/user_properties.py
index f78c412dd8..e4aa0799a8 100644
--- a/frappe/core/page/user_properties/user_properties.py
+++ b/frappe/core/page/user_properties/user_properties.py
@@ -5,13 +5,12 @@ from __future__ import unicode_literals
import frappe
import frappe.defaults
import frappe.permissions
+from frappe.core.doctype.user.user import get_system_users
@frappe.whitelist()
def get_users_and_links():
return {
- "users": frappe.db.sql_list("""select name from tabUser where
- ifnull(enabled,0)=1 and
- name not in ("Administrator", "Guest")"""),
+ "users": get_system_users(),
"link_fields": get_restrictable_doctypes()
}
diff --git a/frappe/model/bean.py b/frappe/model/bean.py
index 93c18719cf..4a2c8f56b6 100644
--- a/frappe/model/bean.py
+++ b/frappe/model/bean.py
@@ -68,9 +68,6 @@ class Bean:
self.set_doclist(doclist)
- if dt == dn:
- self.convert_type(self.doc)
-
def __iter__(self):
return self.doclist.__iter__()
@@ -91,6 +88,10 @@ class Bean:
self.doclist = frappe.doclist(doclist)
self.doc = self.doclist[0]
+
+ if self.doc.get_meta().issingle:
+ self.doc.cast_floats_and_ints()
+
if self.obj:
self.obj.doclist = self.doclist
self.obj.doc = self.doc
@@ -444,16 +445,6 @@ class Bean:
raise frappe.MandatoryError, ", ".join([fieldname for msg, fieldname in missing])
- def convert_type(self, doc):
- if doc.doctype==doc.name and doc.doctype!="DocType":
- for df in self.meta.get({"doctype": "DocField", "parent": doc.doctype}):
- if df.fieldtype in ("Int", "Check"):
- doc.fields[df.fieldname] = cint(doc.fields.get(df.fieldname))
- elif df.fieldtype in ("Float", "Currency"):
- doc.fields[df.fieldname] = flt(doc.fields.get(df.fieldname))
-
- doc.docstatus = cint(doc.docstatus)
-
def extract_images_from_text_editor(self):
from frappe.utils.file_manager import extract_images_from_html
if self.doc.doctype != "DocType":
diff --git a/frappe/model/doc.py b/frappe/model/doc.py
index 1912a75452..18890b0e43 100755
--- a/frappe/model/doc.py
+++ b/frappe/model/doc.py
@@ -161,7 +161,18 @@ class Document:
def _loadsingle(self):
self.name = self.doctype
self.fields.update(getsingle(self.doctype))
-
+ self.cast_floats_and_ints()
+
+ def cast_floats_and_ints(self):
+ for df in frappe.get_doctype(self.doctype).get_docfields():
+ if df.fieldtype in ("Int", "Check"):
+ self.fields[df.fieldname] = cint(self.fields.get(df.fieldname))
+ elif df.fieldtype in ("Float", "Currency"):
+ self.fields[df.fieldname] = flt(self.fields.get(df.fieldname))
+
+ if self.docstatus is not None:
+ self.docstatus = cint(self.docstatus)
+
def __setattr__(self, name, value):
# normal attribute
if not self.__dict__.has_key('_Document__initialized'):
diff --git a/frappe/model/doctype.py b/frappe/model/doctype.py
index 425ff5416e..6d5802a246 100644
--- a/frappe/model/doctype.py
+++ b/frappe/model/doctype.py
@@ -380,10 +380,12 @@ class DocTypeDocList(frappe.model.doclist.DocList):
return fieldname in self.get_fieldnames()
def get_fieldnames(self, filters=None):
+ return map(lambda df: df.fieldname, self.get_docfields(filters))
+
+ def get_docfields(self, filters=None):
if not filters: filters = {}
filters.update({"doctype": "DocField", "parent": self[0].name})
-
- return map(lambda df: df.fieldname, self.get(filters))
+ return self.get(filters)
def get_options(self, fieldname, parent=None, parentfield=None):
return self.get_field(fieldname, parent, parentfield).options
diff --git a/frappe/sessions.py b/frappe/sessions.py
index fdc19b29db..156953d8b9 100644
--- a/frappe/sessions.py
+++ b/frappe/sessions.py
@@ -68,24 +68,26 @@ def get():
"""get session boot info"""
from frappe.core.doctype.notification_count.notification_count import \
get_notification_info_for_boot, get_notifications
+ from frappe.boot import get_bootinfo, get_startup_js
bootinfo = None
- if not getattr(frappe.conf,'disable_session_cache',None):
+ if not getattr(frappe.conf,'disable_session_cache', None):
# check if cache exists
bootinfo = frappe.cache().get_value('bootinfo:' + frappe.session.user)
if bootinfo:
bootinfo['from_cache'] = 1
bootinfo["user"]["recent"] = json.dumps(frappe.cache().get_value("recent:" + frappe.session.user))
bootinfo["notification_info"].update(get_notifications())
+ bootinfo["startup_js"] = get_startup_js()
if not bootinfo:
if not frappe.cache().get_stats():
frappe.msgprint("memcached is not working / stopped. Please start memcached for best results.")
# if not create it
- from frappe.boot import get_bootinfo
bootinfo = get_bootinfo()
bootinfo["notification_info"] = get_notification_info_for_boot()
+ bootinfo["startup_js"] = get_startup_js()
frappe.cache().set_value('bootinfo:' + frappe.session.user, bootinfo)
return bootinfo
diff --git a/frappe/tests/test_db.py b/frappe/tests/test_db.py
index 8d827accfc..81d843d635 100644
--- a/frappe/tests/test_db.py
+++ b/frappe/tests/test_db.py
@@ -5,12 +5,14 @@ from __future__ import unicode_literals
import unittest
import frappe
from frappe.test_runner import make_test_records
+from frappe.core.doctype.user.user import STANDARD_USERS
class TestDB(unittest.TestCase):
def test_get_value(self):
from frappe.utils import now_datetime
import time
- frappe.db.sql("""delete from `tabUser` where name not in ('Administrator', 'Guest')""")
+ frappe.db.sql("""delete from `tabUser` where name not in ({})""".format(", ".join(["%s"]*len(STANDARD_USERS))),
+ STANDARD_USERS)
now = now_datetime()
diff --git a/frappe/utils/email_lib/smtp.py b/frappe/utils/email_lib/smtp.py
index 576a30eab2..9ba7d9e94a 100644
--- a/frappe/utils/email_lib/smtp.py
+++ b/frappe/utils/email_lib/smtp.py
@@ -13,7 +13,7 @@ def send(email, as_bulk=False):
if frappe.flags.mute_emails or frappe.conf.get("mute_emails") or False:
frappe.msgprint("Emails are muted")
return
-
+
try:
smtpserver = SMTPServer()
if hasattr(smtpserver, "always_use_login_id_as_sender") and \
diff --git a/frappe/utils/scheduler.py b/frappe/utils/scheduler.py
index 985e016507..f4d743aaea 100644
--- a/frappe/utils/scheduler.py
+++ b/frappe/utils/scheduler.py
@@ -18,6 +18,9 @@ from datetime import datetime
DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S'
def enqueue_events(site):
+ if is_scheduler_disabled():
+ return
+
# lock before queuing begins
try:
lock = create_lock('scheduler')
@@ -103,6 +106,15 @@ def log(method, message=None):
return message
+def is_scheduler_disabled():
+ return frappe.utils.cint(frappe.db.get_global("disable_scheduler"))
+
+def enable_scheduler():
+ frappe.db.set_global("disable_scheduler", 0)
+
+def disable_scheduler():
+ frappe.db.set_global("disable_scheduler", 1)
+
def get_errors(from_date, to_date, limit):
errors = frappe.db.sql("""select modified, method, error from `tabScheduler Log`
where date(modified) between %s and %s
@@ -127,6 +139,6 @@ def get_error_report(from_date=None, to_date=None, limit=10):
limit=limit, url=get_url(), errors="
Scheduler didn't encounter any problems.
" - + if __name__=='__main__': execute() diff --git a/frappe/utils/user.py b/frappe/utils/user.py index 32e85b8cae..0dee77b9e1 100644 --- a/frappe/utils/user.py +++ b/frappe/utils/user.py @@ -179,13 +179,15 @@ def get_user_fullname(user): def get_system_managers(only_name=False): """returns all system manager's user details""" import email.utils + from frappe.core.doctype.user.user import STANDARD_USERS system_managers = frappe.db.sql("""select distinct name, concat_ws(" ", if(first_name="", null, first_name), if(last_name="", null, last_name)) as fullname from tabUser p where docstatus < 2 and enabled = 1 - and name not in ("Administrator", "Guest") + and name not in ({}) and exists (select * from tabUserRole ur - where ur.parent = p.name and ur.role="System Manager")""", as_dict=True) + where ur.parent = p.name and ur.role="System Manager")""".format(", ".join(["%s"]*len(STANDARD_USERS))), + STANDARD_USERS, as_dict=True) if only_name: return [p.name for p in system_managers] diff --git a/frappe/website/render.py b/frappe/website/render.py index 1f6022c86b..694afc5477 100644 --- a/frappe/website/render.py +++ b/frappe/website/render.py @@ -16,16 +16,28 @@ def render(path): """render html page""" frappe.local.is_ajax = frappe.get_request_header("X-Requested-With")=="XMLHttpRequest" path = resolve_path(path.lstrip("/")) + http_status_code = 200 try: data = render_page(path) + + except frappe.DoesNotExistError, e: + path = "404" + data = render_page(path) + http_status_code = e.http_status_code + except Exception: path = "error" data = render_page(path) + http_status_code = 500 + return build_response(path, data, http_status_code) + +def build_response(path, data, http_status_code): # build response response = Response() response.data = set_content_type(response, data, path) + response.status_code = http_status_code response.headers[b"X-Page-Name"] = path.encode("utf-8") response.headers[b"X-From-Cache"] = frappe.local.response.from_cache or False return response @@ -53,14 +65,16 @@ def build(path): frappe.connect() build_method = (build_json if is_ajax() else build_page) + try: return build_method(path) except frappe.DoesNotExistError: hooks = frappe.get_hooks() if hooks.website_catch_all: - return build_method(hooks.website_catch_all[0]) + path = hooks.website_catch_all[0] + return build_method(path) else: - return build_method("404") + raise def build_json(path): return get_context(path).data