diff --git a/frappe/__init__.py b/frappe/__init__.py index 5da13e5d55..ea7432f562 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -44,7 +44,7 @@ def _(msg): return msg from frappe.translate import get_full_dict - return get_full_dict(local.lang).get(msg, msg) + return get_full_dict(local.lang).get(msg) or msg def get_lang_dict(fortype, name=None): """Returns the translated language dict for the given type and name. @@ -919,6 +919,9 @@ def as_json(obj, indent=1): from frappe.utils.response import json_handler return json.dumps(obj, indent=indent, sort_keys=True, default=json_handler) +def are_emails_muted(): + return flags.mute_emails or conf.get("mute_emails") or False + def get_test_records(doctype): """Returns list of objects from `test_records.json` in the given doctype's folder.""" from frappe.modules import get_doctype_module, get_module_path diff --git a/frappe/__version__.py b/frappe/__version__.py index e062fb2d49..2a69af1984 100644 --- a/frappe/__version__.py +++ b/frappe/__version__.py @@ -1,2 +1,2 @@ from __future__ import unicode_literals -__version__ = "6.1.2" +__version__ = "6.2.0" diff --git a/frappe/boot.py b/frappe/boot.py index 20d5b2f0bf..6a88bbc091 100644 --- a/frappe/boot.py +++ b/frappe/boot.py @@ -69,7 +69,6 @@ def get_bootinfo(): bootinfo['versions'] = {k: v['version'] for k, v in get_versions().items()} bootinfo.error_report_email = frappe.get_hooks("error_report_email") - bootinfo.default_background_image = "/assets/frappe/images/ui/into-the-dawn.jpg" bootinfo.calendars = sorted(frappe.get_hooks("calendars")) return bootinfo diff --git a/frappe/change_log/v6/v6_2_0.md b/frappe/change_log/v6/v6_2_0.md new file mode 100644 index 0000000000..05253243e3 --- /dev/null +++ b/frappe/change_log/v6/v6_2_0.md @@ -0,0 +1,3 @@ +- **Permissions:** + - If User Permissions are missing for a DocType, don't show non-matching records. + - If **Ignore User Permissions If Missing** is checked in System Settings, show records even if User Permissions are not defined. diff --git a/frappe/commands.py b/frappe/commands.py index 28a6a82548..7208095db6 100644 --- a/frappe/commands.py +++ b/frappe/commands.py @@ -682,11 +682,19 @@ def request(context, args): @click.command('doctor') def doctor(): - "Get untranslated strings for lang." + "Get diagnostic info about background workers" from frappe.utils.doctor import doctor as _doctor frappe.init('') return _doctor() +@click.command('celery-doctor') +@click.option('--site', help='site name') +def celery_doctor(site=None): + "Get diagnostic info about background workers" + from frappe.utils.doctor import celery_doctor as _celery_doctor + frappe.init('') + return _celery_doctor(site=site) + @click.command('purge-all-tasks') def purge_all_tasks(): "Purge any pending periodic tasks of 'all' event. Doesn't purge hourly, daily and weekly" @@ -868,6 +876,7 @@ commands = [ serve, request, doctor, + celery_doctor, purge_all_tasks, dump_queue_status, console, diff --git a/frappe/core/doctype/report/report.json b/frappe/core/doctype/report/report.json index 9981a99afc..562cdba6e4 100644 --- a/frappe/core/doctype/report/report.json +++ b/frappe/core/doctype/report/report.json @@ -300,7 +300,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-02-05 05:11:44.753200", + "modified": "2015-09-07 15:51:26", "modified_by": "Administrator", "module": "Core", "name": "Report", @@ -368,7 +368,7 @@ }, { "amend": 0, - "apply_user_permissions": 1, + "apply_user_permissions": 0, "cancel": 0, "create": 0, "delete": 0, diff --git a/frappe/core/doctype/role/role.json b/frappe/core/doctype/role/role.json index 85a026820e..fb4b299077 100644 --- a/frappe/core/doctype/role/role.json +++ b/frappe/core/doctype/role/role.json @@ -41,7 +41,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-02-05 05:11:44.831475", + "modified": "2015-09-07 15:51:26", "modified_by": "Administrator", "module": "Core", "name": "Role", @@ -89,7 +89,7 @@ }, { "amend": 0, - "apply_user_permissions": 1, + "apply_user_permissions": 0, "cancel": 0, "create": 0, "delete": 0, diff --git a/frappe/core/doctype/system_settings/system_settings.json b/frappe/core/doctype/system_settings/system_settings.json index 6eaa88bd55..4142edac7c 100644 --- a/frappe/core/doctype/system_settings/system_settings.json +++ b/frappe/core/doctype/system_settings/system_settings.json @@ -335,6 +335,29 @@ "set_only_once": 0, "unique": 0 }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "description": "eg. If Apply User Permissions is checked for Report DocType but no User Permissions are defined for Report for a User, then all Reports are shown to that User", + "fieldname": "ignore_user_permissions_if_missing", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Ignore User Permissions If Missing", + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -432,7 +455,7 @@ "is_submittable": 0, "issingle": 1, "istable": 0, - "modified": "2015-05-21 07:15:55.682132", + "modified": "2015-09-07 11:36:15.465900", "modified_by": "Administrator", "module": "Core", "name": "System Settings", diff --git a/frappe/custom/doctype/customize_form/customize_form.py b/frappe/custom/doctype/customize_form/customize_form.py index 177be05f6d..2c688a20d1 100644 --- a/frappe/custom/doctype/customize_form/customize_form.py +++ b/frappe/custom/doctype/customize_form/customize_form.py @@ -38,6 +38,8 @@ class CustomizeForm(Document): 'in_filter': 'Check', 'in_list_view': 'Check', 'hidden': 'Check', + 'collapsible': 'Check', + 'collapsible_depends_on': 'Data', 'print_hide': 'Check', 'report_hide': 'Check', 'allow_on_submit': 'Check', diff --git a/frappe/custom/doctype/customize_form_field/customize_form_field.json b/frappe/custom/doctype/customize_form_field/customize_form_field.json index 3c2d7b387c..ac3725240c 100644 --- a/frappe/custom/doctype/customize_form_field/customize_form_field.json +++ b/frappe/custom/doctype/customize_form_field/customize_form_field.json @@ -334,6 +334,52 @@ "unique": 0, "width": "50px" }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "eval:doc.fieldtype==\"Section Break\"", + "fieldname": "collapsible", + "fieldtype": "Check", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Collapsible", + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, + { + "allow_on_submit": 0, + "bold": 0, + "collapsible": 0, + "depends_on": "eval:doc.fieldtype==\"Section Break\"", + "fieldname": "collapsible_depends_on", + "fieldtype": "Data", + "hidden": 0, + "ignore_user_permissions": 0, + "in_filter": 0, + "in_list_view": 0, + "label": "Collapsible Depends On", + "no_copy": 0, + "permlevel": 0, + "precision": "", + "print_hide": 0, + "read_only": 0, + "report_hide": 0, + "reqd": 0, + "search_index": 0, + "set_only_once": 0, + "unique": 0 + }, { "allow_on_submit": 0, "bold": 0, @@ -641,7 +687,7 @@ "is_submittable": 0, "issingle": 0, "istable": 1, - "modified": "2015-07-27 01:00:32.901851", + "modified": "2015-09-04 02:49:57.129449", "modified_by": "Administrator", "module": "Custom", "name": "Customize Form Field", diff --git a/frappe/database.py b/frappe/database.py index a8120234b5..af826acd4e 100644 --- a/frappe/database.py +++ b/frappe/database.py @@ -505,11 +505,23 @@ class Database: def get_list(self, *args, **kwargs): return frappe.get_list(*args, **kwargs) - def get_single_value(self, doctype, fieldname): - """Get property of Single DocType.""" + def get_single_value(self, doctype, fieldname, cache=False): + """Get property of Single DocType. Cache locally by default""" + value = self.value_cache.setdefault(doctype, {}).get(fieldname) + if value: + return value + val = self.sql("""select value from tabSingles where doctype=%s and field=%s""", (doctype, fieldname)) - return val[0][0] if val else None + val = val[0][0] if val else None + + if val=="0" or val=="1": + # check type + val = int(val) + + self.value_cache[doctype][fieldname] = val + + return val def get_singles_value(self, *args, **kwargs): """Alias for get_single_value""" @@ -594,6 +606,10 @@ class Database: self.set_value(dt, dn, "modified", modified) self.set_value(dt, dn, "modified_by", modified_by) + + if dt in self.value_cache: + del self.value_cache[dt] + def set(self, doc, field, val): """Set value in document. **Avoid**""" doc.db_set(field, val) diff --git a/frappe/desk/doctype/event/event.json b/frappe/desk/doctype/event/event.json index 91e80b258b..33adad16c2 100644 --- a/frappe/desk/doctype/event/event.json +++ b/frappe/desk/doctype/event/event.json @@ -635,7 +635,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-02-20 05:08:30.153381", + "modified": "2015-09-07 15:51:26", "modified_by": "Administrator", "module": "Desk", "name": "Event", @@ -643,7 +643,7 @@ "permissions": [ { "amend": 0, - "apply_user_permissions": 1, + "apply_user_permissions": 0, "cancel": 0, "create": 1, "delete": 0, diff --git a/frappe/desk/doctype/feed/feed.json b/frappe/desk/doctype/feed/feed.json index 08c6cd401a..47f0c873a1 100644 --- a/frappe/desk/doctype/feed/feed.json +++ b/frappe/desk/doctype/feed/feed.json @@ -145,7 +145,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-01-07 13:40:10.882588", + "modified": "2015-09-07 15:51:26", "modified_by": "Administrator", "module": "Desk", "name": "Feed", @@ -173,7 +173,7 @@ }, { "amend": 0, - "apply_user_permissions": 1, + "apply_user_permissions": 0, "cancel": 0, "create": 0, "delete": 0, diff --git a/frappe/desk/doctype/note/note.json b/frappe/desk/doctype/note/note.json index 62304b7e4e..bba36ed669 100644 --- a/frappe/desk/doctype/note/note.json +++ b/frappe/desk/doctype/note/note.json @@ -84,7 +84,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-07-28 16:18:12.301520", + "modified": "2015-09-07 15:51:26", "modified_by": "Administrator", "module": "Desk", "name": "Note", @@ -92,7 +92,7 @@ "permissions": [ { "amend": 0, - "apply_user_permissions": 1, + "apply_user_permissions": 0, "cancel": 0, "create": 1, "delete": 1, diff --git a/frappe/desk/doctype/todo/todo.json b/frappe/desk/doctype/todo/todo.json index 1454c5202e..144a4d1165 100644 --- a/frappe/desk/doctype/todo/todo.json +++ b/frappe/desk/doctype/todo/todo.json @@ -335,7 +335,7 @@ "issingle": 0, "istable": 0, "max_attachments": 0, - "modified": "2015-06-11 16:06:34.561469", + "modified": "2015-09-07 15:51:26", "modified_by": "Administrator", "module": "Desk", "name": "ToDo", @@ -343,7 +343,7 @@ "permissions": [ { "amend": 0, - "apply_user_permissions": 1, + "apply_user_permissions": 0, "cancel": 0, "create": 1, "delete": 0, diff --git a/frappe/desk/form/load.py b/frappe/desk/form/load.py index 82cc238068..345c097ad2 100644 --- a/frappe/desk/form/load.py +++ b/frappe/desk/form/load.py @@ -32,7 +32,7 @@ def getdoc(doctype, name, user=None): run_onload(doc) if not doc.has_permission("read"): - raise frappe.PermissionError, "read" + raise frappe.PermissionError, ("read", doctype, name) # add file list get_docinfo(doc) diff --git a/frappe/email/bulk.py b/frappe/email/bulk.py index c5ed6e7ca3..3d958fb51f 100644 --- a/frappe/email/bulk.py +++ b/frappe/email/bulk.py @@ -190,7 +190,7 @@ def flush(from_test=False): # additional check check_bulk_limit([]) - if frappe.flags.mute_emails or frappe.conf.get("mute_emails") or False: + if frappe.are_emails_muted(): msgprint(_("Emails are muted")) from_test = True diff --git a/frappe/email/doctype/standard_reply/standard_reply.json b/frappe/email/doctype/standard_reply/standard_reply.json index f446b97d22..049c724a9e 100644 --- a/frappe/email/doctype/standard_reply/standard_reply.json +++ b/frappe/email/doctype/standard_reply/standard_reply.json @@ -83,7 +83,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-07-28 16:18:12.432775", + "modified": "2015-09-07 15:51:26", "modified_by": "Administrator", "module": "Email", "name": "Standard Reply", @@ -92,7 +92,7 @@ "permissions": [ { "amend": 0, - "apply_user_permissions": 1, + "apply_user_permissions": 0, "cancel": 0, "create": 1, "delete": 0, diff --git a/frappe/email/smtp.py b/frappe/email/smtp.py index 714d64423d..c24ea82807 100644 --- a/frappe/email/smtp.py +++ b/frappe/email/smtp.py @@ -15,7 +15,7 @@ def send(email, append_to=None): frappe.flags.sent_mail = email.as_string() return - if frappe.flags.mute_emails or frappe.conf.get("mute_emails") or False: + if frappe.are_emails_muted(): frappe.msgprint(_("Emails are muted")) return @@ -81,7 +81,7 @@ def get_default_outgoing_email_account(raise_exception_not_set=True): if not email_account and not raise_exception_not_set: return None - if frappe.flags.mute_emails or frappe.conf.get("mute_emails") or False: + if frappe.are_emails_muted(): # create a stub email_account = frappe.new_doc("Email Account") email_account.update({ diff --git a/frappe/geo/doctype/country/country.json b/frappe/geo/doctype/country/country.json index 8098855411..165695d7f5 100644 --- a/frappe/geo/doctype/country/country.json +++ b/frappe/geo/doctype/country/country.json @@ -105,7 +105,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-07-28 16:18:11.855617", + "modified": "2015-09-07 15:51:26", "modified_by": "Administrator", "module": "Geo", "name": "Country", @@ -133,7 +133,7 @@ }, { "amend": 0, - "apply_user_permissions": 1, + "apply_user_permissions": 0, "cancel": 0, "create": 0, "delete": 0, diff --git a/frappe/geo/doctype/currency/currency.json b/frappe/geo/doctype/currency/currency.json index aab3d56931..4219cb9ba9 100644 --- a/frappe/geo/doctype/currency/currency.json +++ b/frappe/geo/doctype/currency/currency.json @@ -152,7 +152,7 @@ "is_submittable": 0, "issingle": 0, "istable": 0, - "modified": "2015-07-13 05:01:14.014983", + "modified": "2015-09-07 15:51:26", "modified_by": "Administrator", "module": "Geo", "name": "Currency", @@ -180,7 +180,7 @@ }, { "amend": 0, - "apply_user_permissions": 1, + "apply_user_permissions": 0, "cancel": 0, "create": 0, "delete": 0, diff --git a/frappe/hooks.py b/frappe/hooks.py index 77d12c98d2..13437285c9 100644 --- a/frappe/hooks.py +++ b/frappe/hooks.py @@ -26,7 +26,7 @@ to ERPNext. """ app_icon = "octicon octicon-circuit-board" -app_version = "6.1.2" +app_version = "6.2.0" app_color = "orange" github_link = "https://github.com/frappe/frappe" diff --git a/frappe/model/db_query.py b/frappe/model/db_query.py index 10f7939d3f..411d16600c 100644 --- a/frappe/model/db_query.py +++ b/frappe/model/db_query.py @@ -323,8 +323,7 @@ class DatabaseQuery(object): tuple([frappe.db.escape(s) for s in self.shared]) def add_user_permissions(self, user_permissions, user_permission_doctypes=None): - user_permission_doctypes = frappe.permissions.get_user_permission_doctypes(user_permission_doctypes, - user_permissions) + user_permission_doctypes = frappe.permissions.get_user_permission_doctypes(user_permission_doctypes, user_permissions) meta = frappe.get_meta(self.doctype) for doctypes in user_permission_doctypes: @@ -332,13 +331,17 @@ class DatabaseQuery(object): match_conditions = [] # check in links for df in meta.get_fields_to_check_permissions(doctypes): - match_conditions.append("""(ifnull(`tab{doctype}`.`{fieldname}`, "")="" - or `tab{doctype}`.`{fieldname}` in ({values}))""".format( - doctype=self.doctype, - fieldname=df.fieldname, - values=", ".join([('"'+frappe.db.escape(v)+'"') for v in user_permissions[df.options]]) - )) - match_filters[df.options] = user_permissions[df.options] + user_permission_values = user_permissions.get(df.options, []) + + condition = 'ifnull(`tab{doctype}`.`{fieldname}`, "")=""'.format(doctype=self.doctype, fieldname=df.fieldname) + if user_permission_values: + condition += """ or `tab{doctype}`.`{fieldname}` in ({values})""".format( + doctype=self.doctype, fieldname=df.fieldname, + values=", ".join([('"'+frappe.db.escape(v)+'"') for v in user_permission_values]) + ) + match_conditions.append("({condition})".format(condition=condition)) + + match_filters[df.options] = user_permission_values if match_conditions: self.match_conditions.append(" and ".join(match_conditions)) diff --git a/frappe/model/db_schema.py b/frappe/model/db_schema.py index 02ddc78a0a..deb27d7eda 100644 --- a/frappe/model/db_schema.py +++ b/frappe/model/db_schema.py @@ -142,7 +142,7 @@ class DbTable: precisions = {} uniques = {} - if not frappe.flags.in_install: + if not frappe.flags.in_install_db and frappe.flags.in_install != "frappe": custom_fl = frappe.db.sql("""\ SELECT * FROM `tabCustom Field` WHERE dt = %s AND docstatus < 2""", (self.doctype,), as_dict=1) diff --git a/frappe/model/document.py b/frappe/model/document.py index 741dcf393a..c945c3394b 100644 --- a/frappe/model/document.py +++ b/frappe/model/document.py @@ -295,6 +295,9 @@ class Document(BaseDocument): frappe.db.sql("""insert into tabSingles(doctype, field, value) values (%s, %s, %s)""", (self.doctype, field, value)) + if self.doctype in frappe.db.value_cache: + del frappe.db.value_cache[self.doctype] + def _set_docstatus_user_and_timestamp(self): self._original_modified = self.modified self.modified = now() diff --git a/frappe/model/mapper.py b/frappe/model/mapper.py index 56677fb528..8623fe83c9 100644 --- a/frappe/model/mapper.py +++ b/frappe/model/mapper.py @@ -43,7 +43,7 @@ def get_mapped_doc(from_doctype, from_docname, table_maps, target_doc=None, table_map = { "doctype": target_child_doctype } - + if table_map: for source_d in source_doc.get(df.fieldname): if "condition" in table_map: @@ -133,10 +133,7 @@ def map_fields(source_doc, target_doc, table_map, source_parent): map_fetch_fields(target_doc, df, no_copy_fields) def map_fetch_fields(target_doc, df, no_copy_fields): - try: - linked_doc = frappe.get_doc(df.options, target_doc.get(df.fieldname)) - except: - return + linked_doc = None # options should be like "link_fieldname.fieldname_in_liked_doc" for fetch_df in target_doc.meta.get("fields", {"options": "^{0}.".format(df.fieldname)}): @@ -145,6 +142,13 @@ def map_fetch_fields(target_doc, df, no_copy_fields): if not target_doc.get(fetch_df.fieldname) and fetch_df.fieldname not in no_copy_fields: source_fieldname = fetch_df.options.split(".")[1] + + if not linked_doc: + try: + linked_doc = frappe.get_doc(df.options, target_doc.get(df.fieldname)) + except: + return + val = linked_doc.get(source_fieldname) if val not in (None, ""): @@ -156,6 +160,7 @@ def map_child_doc(source_d, target_parent, table_map, source_parent=None): target_d = frappe.new_doc(target_child_doctype, target_parent, target_parentfield) map_doc(source_d, target_d, table_map, source_parent) + target_d.idx = None target_parent.append(target_parentfield, target_d) return target_d diff --git a/frappe/patches.txt b/frappe/patches.txt index e00dfd2746..dab9cc73b2 100644 --- a/frappe/patches.txt +++ b/frappe/patches.txt @@ -89,3 +89,4 @@ frappe.patches.v6_0.communication_status_and_permission frappe.patches.v6_0.make_task_log_folder frappe.patches.v6_0.document_type_rename frappe.patches.v6_0.fix_ghana_currency +frappe.patches.v6_2.ignore_user_permissions_if_missing diff --git a/frappe/patches/v6_2/__init__.py b/frappe/patches/v6_2/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/frappe/patches/v6_2/ignore_user_permissions_if_missing.py b/frappe/patches/v6_2/ignore_user_permissions_if_missing.py new file mode 100644 index 0000000000..468f99a83d --- /dev/null +++ b/frappe/patches/v6_2/ignore_user_permissions_if_missing.py @@ -0,0 +1,9 @@ +from __future__ import unicode_literals +import frappe + +def execute(): + frappe.reload_doctype("System Settings") + system_settings = frappe.get_doc("System Settings") + system_settings.ignore_user_permissions_if_missing = 1 + system_settings.flags.ignore_mandatory = 1 + system_settings.save() diff --git a/frappe/permissions.py b/frappe/permissions.py index 15ffb23ef6..0122fbde98 100644 --- a/frappe/permissions.py +++ b/frappe/permissions.py @@ -166,6 +166,7 @@ def get_role_permissions(meta, user=None, verbose=False): perms = frappe._dict({ "apply_user_permissions": {}, "user_permission_doctypes": {}, "if_owner": {} }) user_roles = frappe.get_roles(user) dont_match = [] + has_a_role_with_apply_user_permissions = False for p in meta.permissions: if cint(p.permlevel)==0 and (p.role in user_roles): @@ -186,18 +187,20 @@ def get_role_permissions(meta, user=None, verbose=False): dont_match.append(ptype) if p.apply_user_permissions: + has_a_role_with_apply_user_permissions = True + if p.user_permission_doctypes: # set user_permission_doctypes in perms user_permission_doctypes = json.loads(p.user_permission_doctypes) - - if user_permission_doctypes: - # perms["user_permission_doctypes"][ptype] would be a list of list like [["User", "Blog Post"], ["User"]] - for ptype in rights: - if p.get(ptype): - perms["user_permission_doctypes"].setdefault(ptype, []).append(user_permission_doctypes) else: user_permission_doctypes = get_linked_doctypes(meta.name) + if user_permission_doctypes: + # perms["user_permission_doctypes"][ptype] would be a list of list like [["User", "Blog Post"], ["User"]] + for ptype in rights: + if p.get(ptype): + perms["user_permission_doctypes"].setdefault(ptype, []).append(user_permission_doctypes) + # if atleast one record having both Apply User Permission and If Owner unchecked is found, # don't match for those rights for ptype in rights: @@ -210,9 +213,11 @@ def get_role_permissions(meta, user=None, verbose=False): # if one row has only "Apply User Permissions" checked and another has only "If Owner" checked, # set Apply User Permissions as checked - for ptype in rights: - if perms["if_owner"].get(ptype) and perms["apply_user_permissions"].get(ptype)==0: - perms["apply_user_permissions"][ptype] = 1 + # i.e. the case when there is a role with apply_user_permissions as 1, but resultant apply_user_permissions is 0 + if has_a_role_with_apply_user_permissions: + for ptype in rights: + if perms["if_owner"].get(ptype) and perms["apply_user_permissions"].get(ptype)==0: + perms["apply_user_permissions"][ptype] = 1 # delete 0 values for key, value in perms.get("apply_user_permissions").items(): @@ -239,8 +244,8 @@ def user_has_permission(doc, verbose=True, user=None, user_permission_doctypes=N result = True for df in meta.get_fields_to_check_permissions(doctypes): - if (df.options in user_permissions and d.get(df.fieldname) - and d.get(df.fieldname) not in user_permissions[df.options]): + if (d.get(df.fieldname) + and d.get(df.fieldname) not in user_permissions.get(df.options, [])): result = False if verbose: @@ -334,14 +339,11 @@ def apply_user_permissions(doctype, ptype, user=None): def get_user_permission_doctypes(user_permission_doctypes, user_permissions): """returns a list of list like [["User", "Blog Post"], ["User"]]""" - if user_permission_doctypes: + if cint(frappe.db.get_single_value("System Settings", "ignore_user_permissions_if_missing")): # select those user permission doctypes for which user permissions exist! user_permission_doctypes = [list(set(doctypes).intersection(set(user_permissions.keys()))) for doctypes in user_permission_doctypes] - else: - user_permission_doctypes = [user_permissions.keys()] - if len(user_permission_doctypes) > 1: # OPTIMIZATION # if intersection exists, use that to reduce the amount of querying diff --git a/frappe/print/doctype/letter_head/letter_head.json b/frappe/print/doctype/letter_head/letter_head.json index 4fd3ccb49f..b70dd49587 100644 --- a/frappe/print/doctype/letter_head/letter_head.json +++ b/frappe/print/doctype/letter_head/letter_head.json @@ -116,7 +116,7 @@ "issingle": 0, "istable": 0, "max_attachments": 3, - "modified": "2015-02-05 05:11:40.906941", + "modified": "2015-09-07 15:51:26", "modified_by": "Administrator", "module": "Print", "name": "Letter Head", @@ -144,7 +144,7 @@ }, { "amend": 0, - "apply_user_permissions": 1, + "apply_user_permissions": 0, "cancel": 0, "create": 0, "delete": 0, diff --git a/frappe/public/images/ui/into-the-dawn.jpg b/frappe/public/images/ui/into-the-dawn.jpg deleted file mode 100644 index cfcd4ce636..0000000000 Binary files a/frappe/public/images/ui/into-the-dawn.jpg and /dev/null differ diff --git a/frappe/public/js/frappe/misc/user.js b/frappe/public/js/frappe/misc/user.js index 306ee555d3..a4ba377e0c 100644 --- a/frappe/public/js/frappe/misc/user.js +++ b/frappe/public/js/frappe/misc/user.js @@ -62,13 +62,21 @@ frappe.get_gravatar = function(email_id) { frappe.ui.set_user_background = function(src, selector, style) { if(!selector) selector = "#page-desktop"; if(!style) style = "Fill Screen"; - if(!src) src = frappe.urllib.get_full_url(frappe.boot.default_background_image); + if(src) { + var background = repl('background: url("%(src)s") center center;', {src: src}); + } else { + var background = "background-color: #4B4C9D;"; + } frappe.dom.set_style(repl('%(selector)s { \ - background: url("%(src)s") center center;\ + %(background)s \ background-attachment: fixed; \ %(style)s \ - }', {src:src, selector:selector, style: style==="Fill Screen" ? "background-size: cover;" : ""})); + }', { + selector:selector, + background:background, + style: style==="Fill Screen" ? "background-size: cover;" : "" + })); } frappe.provide('frappe.user'); diff --git a/frappe/public/js/frappe/model/create_new.js b/frappe/public/js/frappe/model/create_new.js index b53b0c8f45..8c29045ede 100644 --- a/frappe/public/js/frappe/model/create_new.js +++ b/frappe/public/js/frappe/model/create_new.js @@ -221,6 +221,7 @@ $.extend(frappe.model, { args: { "source_name": opts.source_name }, + freeze: true, callback: function(r) { if(!r.exc) { var doc = frappe.model.sync(r.message); diff --git a/frappe/share.py b/frappe/share.py index 09fec7b977..85104c0265 100644 --- a/frappe/share.py +++ b/frappe/share.py @@ -12,7 +12,8 @@ def add(doctype, name, user=None, read=1, write=0, share=0, everyone=0, flags=No if not user: user = frappe.session.user - check_share_permission(doctype, name) + if not (flags or {}).get("ignore_share_permission"): + check_share_permission(doctype, name) share_name = get_share_name(doctype, name, user, everyone) diff --git a/frappe/templates/generators/web_form.html b/frappe/templates/generators/web_form.html index 48fe7c02af..512bdd26f6 100644 --- a/frappe/templates/generators/web_form.html +++ b/frappe/templates/generators/web_form.html @@ -153,7 +153,7 @@ {% for section in layout %}
[{""title"":""Jobs"", ""name"":""jobs""}]\
Reference: {{ reference_doctype }} {{ reference_name }} to send document reference,ProTip:添加Reference: {{ reference_doctype }} {{ reference_name }}發送文檔引用
-apps/frappe/frappe/modules/__init__.py +81,App not found,應用程序未找到
+apps/frappe/frappe/modules/__init__.py +81,App not found,未找到應用程式
DocType: Workflow State,pencil,鉛筆
sites/assets/js/form.min.js +283,Share {0} with,分享{0}
DocType: Workflow State,hand-up,手向上
@@ -932,7 +932,7 @@ DocType: DocType,In Dialog,在對話框
apps/frappe/frappe/custom/doctype/customize_form/customize_form.js +142,Help,幫助
DocType: User,Login Before,登錄前
DocType: Web Page,Insert Style,插入樣式
-apps/frappe/frappe/desk/page/applications/applications.js +94,Application Installer,應用程序安裝器
+apps/frappe/frappe/desk/page/applications/applications.js +94,Application Installer,應用程式安裝器
apps/frappe/frappe/core/page/user_permissions/user_permissions.js +246,Is,是
DocType: Workflow State,info-sign,資訊符號
DocType: Currency,"How should this currency be formatted? If not set, will use system defaults",此貨幣使用何種格式?如果沒有設定,將使用系統預設值。
@@ -1116,7 +1116,7 @@ DocType: Website Theme,This must be checked if the below style settings are appl
apps/frappe/frappe/print/page/print_format_builder/print_format_builder.js +111,Name of the new Print Format,新列印格式的名稱
apps/frappe/frappe/core/page/data_import_tool/exporter.py +229,Mandatory:,強制性:
,User Permissions Manager,用戶權限管理
-DocType: Property Setter,New value to be set,新的值被設置
+DocType: Property Setter,New value to be set,被設定的新值
DocType: Email Alert,Days Before or After,日前或後
DocType: Email Alert,Email Alert,電子郵件警報
apps/frappe/frappe/core/page/permission_manager/permission_manager_help.html +34,Select Document Types to set which User Permissions are used to limit access.,選擇文件類型來設置該用戶的權限來限制訪問。
@@ -1327,7 +1327,7 @@ DocType: System Settings,dd.mm.yyyy,dd.mm.yyyy
apps/frappe/frappe/custom/doctype/customize_form/customize_form.js +193,Hide field in Standard Print Format,標準列印格式中的隱藏欄位
DocType: DocField,Float,浮動
DocType: Module Def,Module Name,模塊名稱
-DocType: DocType,DocType is a Table / Form in the application.,DOCTYPE要一個表/表格應用程序中。
+DocType: DocType,DocType is a Table / Form in the application.,DOCTYPE是一應用程式中的表格/表單。
DocType: Feed,Feed Type,Feed類型
DocType: Email Account,GMail,GMail的
DocType: Web Page,Template Path,模板路徑
@@ -1401,14 +1401,14 @@ DocType: Blog Category,Blogger,部落格
sites/assets/js/desk.min.js +528,Date must be in format: {0},日期格式必須是: {0}
apps/frappe/frappe/print/page/print_format_builder/print_format_builder_field.html +22,Select Columns,選擇列
DocType: Workflow State,folder-open,文件夾打開
-apps/frappe/frappe/core/page/desktop/all_applications_dialog.html +1,Search Application,搜索應用程序
+apps/frappe/frappe/core/page/desktop/all_applications_dialog.html +1,Search Application,搜索應用程式
apps/frappe/frappe/config/website.py +18,Single Post (article).,單個帖子(文章)。
DocType: Property Setter,Set Value,設定值
apps/frappe/frappe/custom/doctype/customize_form/customize_form.js +189,Hide field in form,隱藏表單域
DocType: Email Alert,Optional: The alert will be sent if this expression is true,可選:警報會在這個表達式為true發送
apps/frappe/frappe/core/page/permission_manager/permission_manager_help.html +27,You can use Customize Form to set levels on fields.,您可以使用自定義表格中的字段設置的水平。
DocType: DocPerm,Report,報告
-apps/frappe/frappe/templates/generators/web_form.html +31,Please login to create a new {0},請登錄創建一個新的{0}
+apps/frappe/frappe/templates/generators/web_form.html +31,Please login to create a new {0},請登錄建立一個新的{0}
apps/frappe/frappe/desk/reportview.py +69,{0} is saved,{0}已儲存
apps/frappe/frappe/core/doctype/user/user.py +235,User {0} cannot be renamed,用戶{0}無法重命名
apps/frappe/frappe/website/doctype/website_settings/website_settings.js +17,Exported,出口
@@ -1423,7 +1423,7 @@ DocType: Workflow State,chevron-left,人字形-左
DocType: Bulk Email,Sending,發出
apps/frappe/frappe/auth.py +195,Not allowed from this IP Address,不接受來自此IP地址
DocType: Website Slideshow,This goes above the slideshow.,這正好幻燈片上面。
-apps/frappe/frappe/config/setup.py +208,Install Applications.,安裝應用程序。
+apps/frappe/frappe/config/setup.py +208,Install Applications.,安裝應用程式。
DocType: Event,Private,私人
DocType: Print Settings,Send Email Print Attachments as PDF (Recommended),發送郵件列印附件為PDF格式(推薦)
DocType: Workflow Action,Workflow Action,工作流程執行
diff --git a/frappe/utils/doctor.py b/frappe/utils/doctor.py
index 21f4fc213e..d443f3b3bf 100644
--- a/frappe/utils/doctor.py
+++ b/frappe/utils/doctor.py
@@ -13,11 +13,12 @@ def get_redis_conn():
r = conn.default_channel.client
return r
-def get_queues():
+def get_queues(site=None):
"Returns the name of queues where frappe enqueues tasks as per the configuration"
queues = ["celery"]
if frappe.conf.celery_queue_per_site:
- for site in frappe.utils.get_sites():
+ sites = [site] if site else frappe.utils.get_sites()
+ for site in sites:
queues.append(site)
queues.append('longjobs@' + site)
return queues
@@ -71,13 +72,13 @@ def check_if_workers_online():
return True
return False
-def dump_queue_status():
+def dump_queue_status(site=None):
"""
Dumps pending events and tasks per queue
"""
ret = []
r = get_redis_conn()
- for queue in get_queues():
+ for queue in get_queues(site=site):
queue_details = {
'queue': queue,
'len': r.llen(queue),
@@ -106,6 +107,26 @@ def get_task_count_for_queue(queue):
'event_counts': event_counts
}
+def get_running_tasks():
+ ret = {}
+ app = get_celery()
+ inspect = app.control.inspect()
+ active = inspect.active()
+ if not active:
+ return []
+ for worker in active:
+ ret[worker] = []
+ for task in active[worker]:
+ ret[worker].append({
+ 'id': task['id'],
+ 'name': task['name'],
+ 'routing_key': task['delivery_info']['routing_key'],
+ 'args': task['args'],
+ 'kwargs': task['kwargs']
+ })
+ return ret
+
+
def doctor():
"""
Prints diagnostic information for the scheduler
@@ -121,3 +142,13 @@ def doctor():
if (not workers_online) or (pending_tasks > 4000) or locks:
return 1
return True
+
+def celery_doctor(site=None):
+ queues = dump_queue_status(site=site)
+ running_tasks = get_running_tasks()
+ print 'Queue Status'
+ print '------------'
+ print json.dumps(queues, indent=1)
+ print 'Running Tasks'
+ print '------------'
+ print json.dumps(running_tasks, indent=1)
diff --git a/frappe/website/doctype/blog_category/blog_category.json b/frappe/website/doctype/blog_category/blog_category.json
index 56b9913279..373df96e26 100644
--- a/frappe/website/doctype/blog_category/blog_category.json
+++ b/frappe/website/doctype/blog_category/blog_category.json
@@ -126,7 +126,7 @@
"is_submittable": 0,
"issingle": 0,
"istable": 0,
- "modified": "2015-07-28 16:18:11.486847",
+ "modified": "2015-09-07 15:51:26",
"modified_by": "Administrator",
"module": "Website",
"name": "Blog Category",
@@ -154,7 +154,7 @@
},
{
"amend": 0,
- "apply_user_permissions": 1,
+ "apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
diff --git a/frappe/website/doctype/blog_post/blog_post.json b/frappe/website/doctype/blog_post/blog_post.json
index fd2c8049f1..ab3f83e041 100644
--- a/frappe/website/doctype/blog_post/blog_post.json
+++ b/frappe/website/doctype/blog_post/blog_post.json
@@ -272,7 +272,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 5,
- "modified": "2015-04-29 01:46:16.190210",
+ "modified": "2015-09-07 15:51:26",
"modified_by": "Administrator",
"module": "Website",
"name": "Blog Post",
@@ -300,7 +300,7 @@
},
{
"amend": 0,
- "apply_user_permissions": 1,
+ "apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 0,
diff --git a/frappe/website/doctype/blogger/blogger.json b/frappe/website/doctype/blogger/blogger.json
index 5982b44155..a862f754e6 100644
--- a/frappe/website/doctype/blogger/blogger.json
+++ b/frappe/website/doctype/blogger/blogger.json
@@ -171,7 +171,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 1,
- "modified": "2015-07-28 16:18:11.567110",
+ "modified": "2015-09-07 15:51:26",
"modified_by": "Administrator",
"module": "Website",
"name": "Blogger",
@@ -199,7 +199,7 @@
},
{
"amend": 0,
- "apply_user_permissions": 1,
+ "apply_user_permissions": 0,
"cancel": 0,
"create": 0,
"delete": 0,
diff --git a/setup.py b/setup.py
index 66d00c7e23..9d929c073c 100644
--- a/setup.py
+++ b/setup.py
@@ -1,6 +1,6 @@
from setuptools import setup, find_packages
-version = "6.1.2"
+version = "6.2.0"
with open("requirements.txt", "r") as f:
install_requires = f.readlines()