Merge branch 'user_permission_cleanup' of https://github.com/anurag810/frappe into user_permission_cleanup

This commit is contained in:
Anurag Mishra 2019-02-07 18:19:52 +05:30
commit 44db8b4825
24 changed files with 91 additions and 34 deletions

View file

@ -23,7 +23,7 @@ if sys.version[0] == '2':
reload(sys)
sys.setdefaultencoding("utf-8")
__version__ = '11.1.1'
__version__ = '11.1.4'
__title__ = "Frappe Framework"
local = Local()

View file

@ -34,8 +34,10 @@ def import_data(data_import):
frappe.db.set_value("Data Import", data_import, "import_status", "In Progress", update_modified=False)
frappe.publish_realtime("data_import_progress", {"progress": "0",
"data_import": data_import, "reload": True}, user=frappe.session.user)
from frappe.core.page.background_jobs.background_jobs import get_info
enqueued_jobs = [d.get("job_name") for d in get_info()]
if data_import not in enqueued_jobs:
enqueue(upload, queue='default', timeout=6000, event='data_import', job_name=data_import,
data_import_doc=data_import, from_data_import="Yes", user=frappe.session.user)

View file

@ -16,7 +16,7 @@ from frappe.utils.csvutils import getlink
from frappe.utils.dateutils import parse_date
from frappe.utils.file_manager import save_url
from frappe.utils import cint, cstr, flt, getdate, get_datetime, get_url, get_url_to_form
from frappe.utils import cint, cstr, flt, getdate, get_datetime, get_url, get_absolute_url
from six import text_type, string_types
@ -411,31 +411,44 @@ def upload(rows = None, submit_after_import=None, ignore_encoding_errors=False,
# log errors
if parentfield:
log(**{"row": doc.idx, "title": 'Inserted row for "%s"' % (as_link(parenttype, doc.parent)),
"link": get_url_to_form(parenttype, doc.parent), "message": 'Document successfully saved', "indicator": "green"})
"link": get_absolute_url(parenttype, doc.parent), "message": 'Document successfully saved', "indicator": "green"})
elif submit_after_import:
log(**{"row": row_idx + 1, "title":'Submitted row for "%s"' % (as_link(doc.doctype, doc.name)),
"message": "Document successfully submitted", "link": get_url_to_form(doc.doctype, doc.name), "indicator": "blue"})
"message": "Document successfully submitted", "link": get_absolute_url(doc.doctype, doc.name), "indicator": "blue"})
elif original:
log(**{"row": row_idx + 1,"title":'Updated row for "%s"' % (as_link(doc.doctype, doc.name)),
"message": "Document successfully updated", "link": get_url_to_form(doc.doctype, doc.name), "indicator": "green"})
"message": "Document successfully updated", "link": get_absolute_url(doc.doctype, doc.name), "indicator": "green"})
elif not update_only:
log(**{"row": row_idx + 1, "title":'Inserted row for "%s"' % (as_link(doc.doctype, doc.name)),
"message": "Document successfully saved", "link": get_url_to_form(doc.doctype, doc.name), "indicator": "green"})
"message": "Document successfully saved", "link": get_absolute_url(doc.doctype, doc.name), "indicator": "green"})
else:
log(**{"row": row_idx + 1, "title":'Ignored row for %s' % (row[1]), "link": None,
"message": "Document updation ignored", "indicator": "orange"})
except Exception as e:
error_flag = True
err_msg = frappe.local.message_log and "\n".join([json.loads(msg).get('message') for msg in frappe.local.message_log]) or cstr(e)
# build error message
if frappe.local.message_log:
err_msg = "\n".join(['<p class="border-bottom small">{}</p>'.format(json.loads(msg).get('message')) for msg in frappe.local.message_log])
else:
err_msg = '<p class="border-bottom small">{}</p>'.format(cstr(e))
error_trace = frappe.get_traceback()
if error_trace:
error_log_doc = frappe.log_error(error_trace)
error_link = get_url_to_form("Error Log", error_log_doc.name)
error_link = get_absolute_url("Error Log", error_log_doc.name)
else:
error_link = None
log(**{"row": row_idx + 1, "title":'Error for row %s' % (len(row)>1 and frappe.safe_decode(row[1]) or ""), "message": err_msg,
"indicator": "red", "link":error_link})
log(**{
"row": row_idx + 1,
"title": 'Error for row %s' % (len(row)>1 and frappe.safe_decode(row[1]) or ""),
"message": err_msg,
"indicator": "red",
"link":error_link
})
# data with error to create a new file
# include the errored data in the last row as last_error_row_idx will not be updated for the last row
if skip_errors:

View file

@ -6,19 +6,19 @@
<th style="width:40%"> {{ __("Row Status") }} </th>
<th style="width:50%"> {{ __("Message") }} </th>
</tr>
{% for row in data %}
{% if (!show_only_errors) || (show_only_errors && row.indicator == "red") %}
<tr>
<td>
<span>{{ row.row }} </span>
<span>{{ row.row }} </span>
</td>
<td>
<span class="indicator {{ row.indicator }}"> {{ row.title }} </span>
</td>
<td>
{% if (import_status != "Failed" || (row.indicator == "red")) { %}
<span> {{ row.message }} </span>
<div>{{ row.message }}</div>
{% if row.link %}
<span style="width: 10%; float:right;">
<a class="btn-open no-decoration" title="Open Link" href="{{ row.link }}">

View file

@ -150,6 +150,8 @@ class Report(Document):
if params.get('sort_by'):
order_by = _format(params.get('sort_by').split('.')) + ' ' + params.get('sort_order')
elif params.get('order_by'):
order_by = params.get('order_by')
else:
order_by = _format([self.ref_doctype, 'modified']) + ' desc'

View file

@ -358,6 +358,9 @@ class User(Document):
where `%s`=%s""" % \
(tab[0], field, '%s', field, '%s'), (new_name, old_name))
if frappe.db.exists("Chat Profile", old_name):
frappe.rename_doc("Chat Profile", old_name, new_name, force=True)
# set email
frappe.db.sql("""\
update `tabUser` set email=%s
@ -930,7 +933,7 @@ def handle_password_test_fail(result):
suggestions = result['feedback']['suggestions'][0] if result['feedback']['suggestions'] else ''
warning = result['feedback']['warning'] if 'warning' in result['feedback'] else ''
suggestions += "<br>" + _("Hint: Include symbols, numbers and capital letters in the password") + '<br>'
frappe.throw(_('Invalid Password: ' + ' '.join([warning, suggestions])))
frappe.throw(' '.join([_('Invalid Password:'), warning, suggestions]))
def update_gravatar(name):
gravatar = has_gravatar(name)

View file

@ -192,7 +192,9 @@ def run(report_name, filters=None, user=None):
def get_prepared_report_result(report, filters, dn="", user=None):
latest_report_data = {}
# Only look for completed prepared reports with given filters.
doc_list = frappe.get_all("Prepared Report", filters={"status": "Completed", "report_name": report.name, "filters": json.dumps(filters), "owner": user})
doc_list = frappe.get_all("Prepared Report",
filters={"status": "Completed", "report_name": report.name, "filters": filters, "owner": user})
doc = None
if len(doc_list):
if dn:

View file

@ -214,7 +214,7 @@ def delete_items():
"""delete selected items"""
import json
il = sorted(json.loads(frappe.form_dict.get('items')), reverse=True, key=frappe.safe_decode)
il = sorted(json.loads(frappe.form_dict.get('items')), reverse=True)
doctype = frappe.form_dict.get('doctype')
failed = []

View file

@ -547,10 +547,20 @@ class BaseDocument(object):
# single doctype value type is mediumtext
return
column_types_to_check_length = ('varchar', 'int', 'bigint')
for fieldname, value in iteritems(self.get_valid_dict()):
df = self.meta.get_field(fieldname)
if df and df.fieldtype in type_map and type_map[df.fieldtype][0]=="varchar":
max_length = cint(df.get("length")) or cint(varchar_len)
if not df or df.fieldtype == 'Check':
# skip standard fields and Check fields
continue
column_type = type_map[df.fieldtype][0] or None
default_column_max_length = type_map[df.fieldtype][1] or None
if df and df.fieldtype in type_map and column_type in column_types_to_check_length:
max_length = cint(df.get("length")) or cint(default_column_max_length)
if len(cstr(value)) > max_length:
if self.parentfield and self.idx:

View file

@ -234,3 +234,4 @@ frappe.patches.v11_0.migrate_report_settings_for_new_listview
frappe.patches.v11_0.delete_all_prepared_reports
frappe.patches.v11_0.fix_order_by_in_reports_json
execute:frappe.delete_doc('Page', 'applications', ignore_missing=True)
frappe.patches.v11_0.set_missing_creation_and_modified_value_for_user_permissions

View file

@ -43,9 +43,9 @@ def execute():
# only specific doctypes are selected
# split this into multiple records and delete
linked_doctypes = get_linked_doctypes(user_permission.allow, True).keys()
linked_doctypes = list(linked_doctypes)
# append the doctype for which we have build the user permission
linked_doctypes += [user_permission.allow]
@ -56,14 +56,16 @@ def execute():
user_permission.skip_for_doctype = None
for doctype in applicable_for_doctypes:
if doctype:
# Maintain sequence (name, user, allow, for_value, applicable_for, apply_to_all_doctypes)
# Maintain sequence (name, user, allow, for_value, applicable_for, apply_to_all_doctypes, creation, modified)
new_user_permissions_list.append((
frappe.generate_hash("", 10),
user_permission.user,
user_permission.allow,
user_permission.for_value,
doctype,
0
0,
user_permission.creation,
user_permission.modified
))
else:
# No skip_for_doctype found! Just update apply_to_all_doctypes.
@ -72,7 +74,7 @@ def execute():
if new_user_permissions_list:
frappe.db.sql('''
INSERT INTO `tabUser Permission`
(`name`, `user`, `allow`, `for_value`, `applicable_for`, `apply_to_all_doctypes`)
(`name`, `user`, `allow`, `for_value`, `applicable_for`, `apply_to_all_doctypes`, `creation`, `modified`)
VALUES {}
'''.format( # nosec
', '.join(['%s'] * len(new_user_permissions_list))

View file

@ -0,0 +1,6 @@
import frappe
def execute():
frappe.db.sql('''UPDATE `tabUser Permission`
SET `modified`=NOW(), `creation`=NOW()
WHERE `creation` IS NULL''')

View file

@ -1,4 +1,4 @@
<div class="print-format-builder-section row light-bg" data-label="{{ section.label || '' }}">
<div class="print-format-builder-section row light-bg" data-label="{{ section.label }}">
<div class="print-format-builder-section-head">
<a class="section-settings pull-right
btn-default btn-xs" style="padding-top: 3px">

View file

@ -684,7 +684,7 @@ export default class Grid {
data.push(["------"]);
$.each(frappe.get_meta(me.df.options).fields, function(i, df) {
// don't include the read-only field in the template
if(frappe.model.is_value_type(df.fieldtype) && !df.read_only) {
if(frappe.model.is_value_type(df.fieldtype)) {
data[1].push(df.label);
data[2].push(df.fieldname);
let description = (df.description || "") + ' ';

View file

@ -801,7 +801,9 @@ frappe.views.ReportView = frappe.ui.BaseList.extend({
});
this.page.add_menu_item(__("Delete"), function() {
var delete_list = $.map(me.get_checked_items(), function(d) { return d.name; });
var delete_list = $.map(me.get_checked_items(), function(d) {
return d.name.toString();
});
if(!delete_list.length)
return;
if(frappe.confirm(__("This is PERMANENT action and you cannot undo. Continue?"),

View file

@ -32,6 +32,7 @@
frappe.ready_events.push(fn);
}
window.dev_server = {{ dev_server }};
window.socketio_port = {{ frappe.socketio_port }};
</script>
</head>
{% block body %}

View file

@ -1,4 +1,4 @@
{% if blog_title and not (frappe.local.form_dict.txt or frappe.local.form_dict.by) %}
{% if blog_title and not (form_dict.txt or form_dict.by) %}
<div class="page-hero border-bottom">
<div class="container">
<h1 class="page-title">

View file

@ -15,7 +15,7 @@
<script>
frappe.ready(function() {
if(frappe.utils.get_url_arg("search")) {
$(".item-search-results").html('{{ _("Search results for") + ": " + html2text(frappe.form_dict.search or "")|trim }}');
$(".item-search-results").html('{{ _("Search results for") + ": " + html2text(frappe.form_dict.search or "") | e | trim }}');
$(".item-search").toggle(false);
$(".clear").toggle(true);
}

View file

@ -745,6 +745,9 @@ def get_link_to_form(doctype, name, label=None):
return """<a href="{0}">{1}</a>""".format(get_url_to_form(doctype, name), label)
def get_absolute_url(doctype, name):
return "desk#Form/{0}/{1}".format(quoted(doctype), quoted(name))
def get_url_to_form(doctype, name):
return get_url(uri = "desk#Form/{0}/{1}".format(quoted(doctype), quoted(name)))

View file

@ -311,7 +311,7 @@ def sync_global_search():
:return:
"""
while frappe.cache().llen('global_search_queue') > 0:
value = json.loads(frappe.cache().lpop('global_search_queue'))
value = json.loads(frappe.cache().lpop('global_search_queue').decode('utf-8'))
sync_value(value)
def sync_value(value):

View file

@ -56,7 +56,7 @@ def render_template(template, context, is_path=None, safe_render=True):
:param template: path or HTML containing the jinja template
:param context: dict of properties to pass to the template
:param is_path: (optional) assert that the `template` parameter is a path
:param safe_render: (optional) prevent server side scripting via jinja templating
:param safe_render: (optional) prevent server side scripting via jinja templating
'''
from frappe import throw
@ -117,7 +117,6 @@ def get_allowed_functions_for_jenv():
'date_format': date_format,
"format_date": frappe.utils.data.global_date_format,
"form_dict": getattr(frappe.local, 'form_dict', {}),
"local": frappe.local,
"get_hooks": frappe.get_hooks,
"get_meta": frappe.get_meta,
"get_doc": frappe.get_doc,
@ -130,10 +129,12 @@ def get_allowed_functions_for_jenv():
"get_gravatar": frappe.utils.get_gravatar_url,
"full_name": frappe.local.session.data.full_name if getattr(frappe.local, "session", None) else "Guest",
"render_template": frappe.render_template,
"request": getattr(frappe.local, 'request', {}),
'session': {
'user': user,
'csrf_token': frappe.local.session.data.csrf_token if getattr(frappe.local, "session", None) else ''
},
"socketio_port": frappe.conf.socketio_port,
},
'style': {
'border_color': '#d1d8dd'

View file

@ -90,13 +90,13 @@ def download_pdf(doctype, name, format=None, doc=None, no_letterhead=0):
html = frappe.get_print(doctype, name, format, doc=doc, no_letterhead=no_letterhead)
frappe.local.response.filename = "{name}.pdf".format(name=name.replace(" ", "-").replace("/", "-"))
frappe.local.response.filecontent = get_pdf(html)
frappe.local.response.type = "download"
frappe.local.response.type = "pdf"
@frappe.whitelist()
def report_to_pdf(html, orientation="Landscape"):
frappe.local.response.filename = "report.pdf"
frappe.local.response.filecontent = get_pdf(html, {"orientation": orientation})
frappe.local.response.type = "download"
frappe.local.response.type = "pdf"
@frappe.whitelist()
def print_by_server(doctype, name, print_format=None, doc=None, no_letterhead=0):

View file

@ -42,6 +42,7 @@ def build_response(response_type=None):
'txt': as_txt,
'download': as_raw,
'json': as_json,
'pdf': as_pdf,
'page': as_page,
'redirect': redirect,
'binary': as_binary
@ -84,6 +85,13 @@ def as_json():
response.data = json.dumps(frappe.local.response, default=json_handler, separators=(',',':'))
return response
def as_pdf():
response = Response()
response.mimetype = "application/pdf"
response.headers["Content-Disposition"] = ("filename=\"%s\"" % frappe.response['filename'].replace(' ', '_')).encode("utf-8")
response.data = frappe.response['filecontent']
return response
def as_binary():
response = Response()
response.mimetype = 'application/octet-stream'

View file

@ -427,5 +427,6 @@ frappe.ready(function() {
});
}
}
})
});
frappe.socketio.init(window.socketio_port);
});