Преглед изворни кода

Merge branch 'version-12-hotfix' into version-12

version-14
Sahil Khan пре 5 година
родитељ
комит
0de729ff3d
21 измењених фајлова са 112 додато и 36 уклоњено
  1. +1
    -1
      frappe/__init__.py
  2. +4
    -1
      frappe/commands/scheduler.py
  3. +6
    -0
      frappe/core/page/background_jobs/background_jobs.js
  4. +8
    -0
      frappe/core/page/background_jobs/background_jobs.py
  5. +1
    -1
      frappe/desk/moduleview.py
  6. +1
    -0
      frappe/desk/reportview.py
  7. +2
    -1
      frappe/desk/search.py
  8. +17
    -3
      frappe/model/db_query.py
  9. +2
    -2
      frappe/patches/v12_0/fix_public_private_files.py
  10. +3
    -1
      frappe/public/js/frappe/views/components/DeskSection.vue
  11. +1
    -1
      frappe/public/js/frappe/views/file/file_view.js
  12. +3
    -0
      frappe/public/js/frappe/views/pageview.js
  13. +9
    -3
      frappe/utils/data.py
  14. +12
    -1
      frappe/utils/doctor.py
  15. +1
    -1
      frappe/utils/html_utils.py
  16. +3
    -2
      frappe/utils/jinja.py
  17. +13
    -7
      frappe/utils/scheduler.py
  18. +3
    -1
      frappe/website/doctype/personal_data_download_request/personal_data_download_request.py
  19. +15
    -8
      frappe/website/doctype/personal_data_download_request/test_personal_data_download_request.py
  20. +1
    -1
      frappe/www/login.html
  21. +6
    -1
      frappe/www/sitemap.py

+ 1
- 1
frappe/__init__.py Прегледај датотеку

@@ -23,7 +23,7 @@ if sys.version[0] == '2':
reload(sys)
sys.setdefaultencoding("utf-8")

__version__ = '12.0.3'
__version__ = '12.0.4'
__title__ = "Frappe Framework"

local = Local()


+ 4
- 1
frappe/commands/scheduler.py Прегледај датотеку

@@ -115,9 +115,12 @@ def set_maintenance_mode(context, state, site=None):

@click.command('doctor') #Passing context always gets a site and if there is no use site it breaks
@click.option('--site', help='site name')
def doctor(site=None):
@pass_context
def doctor(context, site=None):
"Get diagnostic info about background workers"
from frappe.utils.doctor import doctor as _doctor
if not site:
site = get_site(context)
return _doctor(site=site)

@click.command('show-pending-jobs')


+ 6
- 0
frappe/core/page/background_jobs/background_jobs.js Прегледај датотеку

@@ -13,6 +13,12 @@ frappe.pages['background_jobs'].on_page_load = function(wrapper) {

frappe.pages['background_jobs'].on_page_show = function(wrapper) {
frappe.pages.background_jobs.refresh_jobs();
frappe.call({
method: 'frappe.core.page.background_jobs.background_jobs.get_scheduler_status',
callback: function(r) {
frappe.pages.background_jobs.page.set_indicator(...r.message);
}
});
}

frappe.pages.background_jobs.refresh_jobs = function() {


+ 8
- 0
frappe/core/page/background_jobs/background_jobs.py Прегледај датотеку

@@ -7,6 +7,8 @@ import frappe
from rq import Queue, Worker
from frappe.utils.background_jobs import get_redis_conn
from frappe.utils import format_datetime, cint
from frappe.utils.scheduler import is_scheduler_inactive
from frappe import _

colors = {
'queued': 'orange',
@@ -49,3 +51,9 @@ def get_info(show_failed=False):
for j in q.get_jobs()[:10]: add_job(j, q.name)

return jobs

@frappe.whitelist()
def get_scheduler_status():
if is_scheduler_inactive():
return [_("Inactive"), "red"]
return [_("Active"), "green"]

+ 1
- 1
frappe/desk/moduleview.py Прегледај датотеку

@@ -336,7 +336,7 @@ def get_desktop_settings():
if category in user_saved_modules_by_category:
user_modules = user_saved_modules_by_category[category]
user_modules_by_category[category] = [apply_user_saved_links(modules_by_name[m]) \
for m in user_modules]
for m in user_modules if modules_by_name.get(m)]
else:
user_modules_by_category[category] = [apply_user_saved_links(m) \
for m in all_modules if m.get('category') == category]


+ 1
- 0
frappe/desk/reportview.py Прегледај датотеку

@@ -68,6 +68,7 @@ def get_form_params():

# queries must always be server side
data.query = None
data.strict = None

return data



+ 2
- 1
frappe/desk/search.py Прегледај датотеку

@@ -153,7 +153,8 @@ def search_widget(doctype, txt, query=None, searchfield=None, start=0,
order_by=order_by,
ignore_permissions=ignore_permissions,
reference_doctype=reference_doctype,
as_list=not as_dict)
as_list=not as_dict,
strict=False)

if doctype in UNTRANSLATED_DOCTYPES:
values = tuple([v for v in list(values) if re.search(txt+".*", (_(v.name) if as_dict else _(v[0])), re.IGNORECASE)])


+ 17
- 3
frappe/model/db_query.py Прегледај датотеку

@@ -36,7 +36,7 @@ class DatabaseQuery(object):
ignore_permissions=False, user=None, with_comment_count=False,
join='left join', distinct=False, start=None, page_length=None, limit=None,
ignore_ifnull=False, save_user_settings=False, save_user_settings_fields=False,
update=None, add_total_row=None, user_settings=None, reference_doctype=None, return_query=False):
update=None, add_total_row=None, user_settings=None, reference_doctype=None, return_query=False, strict=True):
if not ignore_permissions and not frappe.has_permission(self.doctype, "read", user=user):
frappe.flags.error_message = _('Insufficient Permission for {0}').format(frappe.bold(self.doctype))
raise frappe.PermissionError(self.doctype)
@@ -80,6 +80,7 @@ class DatabaseQuery(object):
self.update = update
self.user_settings_fields = copy.deepcopy(self.fields)
self.return_query = return_query
self.strict = strict

# for contextual user permission check
# to determine which user permission is applicable on link field of specific doctype
@@ -115,8 +116,12 @@ class DatabaseQuery(object):
args.fields = 'distinct ' + args.fields
args.order_by = '' # TODO: recheck for alternative

query = """select %(fields)s from %(tables)s %(conditions)s
%(group_by)s %(order_by)s %(limit)s""" % args
query = """select %(fields)s
from %(tables)s
%(conditions)s
%(group_by)s
%(order_by)s
%(limit)s""" % args

if self.return_query:
return query
@@ -240,6 +245,12 @@ class DatabaseQuery(object):

_is_query(field)

if self.strict:
if re.compile(r".*/\*.*").match(field):
frappe.throw(_('Illegal SQL Query'))

if re.compile(r".*\s(union).*\s").match(field.lower()):
frappe.throw(_('Illegal SQL Query'))

def extract_tables(self):
"""extract tables from fields"""
@@ -688,6 +699,8 @@ class DatabaseQuery(object):
if 'select' in _lower and ' from ' in _lower:
frappe.throw(_('Cannot use sub-query in order by'))

if re.compile(r".*[^a-z0-9-_ ,`'\"\.\(\)].*").match(_lower):
frappe.throw(_('Illegal SQL Query'))

for field in parameters.split(","):
if "." in field and field.strip().startswith("`tab"):
@@ -755,6 +768,7 @@ def get_list(doctype, *args, **kwargs):
kwargs.pop('cmd', None)
kwargs.pop('ignore_permissions', None)
kwargs.pop('data', None)
kwargs.pop('strict', None)

# If doctype is child table
if frappe.is_table(doctype):


+ 2
- 2
frappe/patches/v12_0/fix_public_private_files.py Прегледај датотеку

@@ -7,7 +7,7 @@ def execute():
filters={'is_folder': 0})

for file in files:
file_url = file.file_url
file_url = file.file_url or ""
if file.is_private:
if not file_url.startswith('/private/files/'):
generate_file(file.name)
@@ -32,4 +32,4 @@ def generate_file(file_name):
except IOError:
pass
except Exception as e:
print(e)
print(e)

+ 3
- 1
frappe/public/js/frappe/views/components/DeskSection.vue Прегледај датотеку

@@ -30,7 +30,9 @@ export default {
}
},
mounted() {
this.setup_sortable();
if (!frappe.utils.is_mobile()) {
this.setup_sortable();
}
},
methods: {
setup_sortable() {


+ 1
- 1
frappe/public/js/frappe/views/file/file_view.js Прегледај датотеку

@@ -354,7 +354,7 @@ frappe.views.FileView.grid_view = frappe.get_user_settings('File').grid_view ||

function redirect_to_home_if_invalid_route() {
const route = frappe.get_route();
if (route[2] !== 'Home') {
if (route[2] === 'List') {
// if the user somehow redirects to List/File/List
// redirect back to Home
frappe.set_route('List', 'File', 'Home');


+ 3
- 0
frappe/public/js/frappe/views/pageview.js Прегледај датотеку

@@ -98,6 +98,9 @@ frappe.views.Page = Class.extend({
this.wrapper.innerHTML = this.pagedoc.content;
frappe.dom.eval(this.pagedoc.__script || this.pagedoc.script || '');
frappe.dom.set_style(this.pagedoc.style || '');

// set breadcrumbs
frappe.breadcrumbs.add(this.pagedoc.module || null);
}

this.trigger_page_event('on_page_load');


+ 9
- 3
frappe/utils/data.py Прегледај датотеку

@@ -714,9 +714,10 @@ def get_url(uri=None, full_address=False):
return uri

if not host_name:
if hasattr(frappe.local, "request") and frappe.local.request and frappe.local.request.host:
protocol = 'https://' if 'https' == frappe.get_request_header('X-Forwarded-Proto', "") else 'http://'
host_name = protocol + frappe.local.request.host
request_host_name = get_host_name_from_request()

if request_host_name:
host_name = request_host_name

elif frappe.local.site:
protocol = 'http://'
@@ -753,6 +754,11 @@ def get_url(uri=None, full_address=False):

return url

def get_host_name_from_request():
if hasattr(frappe.local, "request") and frappe.local.request and frappe.local.request.host:
protocol = 'https://' if 'https' == frappe.get_request_header('X-Forwarded-Proto', "") else 'http://'
return protocol + frappe.local.request.host

def url_contains_port(url):
parts = url.split(':')
return len(parts) > 2


+ 12
- 1
frappe/utils/doctor.py Прегледај датотеку

@@ -3,7 +3,7 @@ import frappe.utils
from collections import defaultdict
from rq import Worker, Connection
from frappe.utils.background_jobs import get_redis_conn, get_queue, get_queue_list
from frappe.utils.scheduler import is_scheduler_disabled
from frappe.utils.scheduler import is_scheduler_disabled, is_scheduler_inactive
from six import iteritems


@@ -107,8 +107,19 @@ def doctor(site=None):
for s in sites:
frappe.init(s)
frappe.connect()

if is_scheduler_disabled():
print("Scheduler disabled for", s)

if frappe.local.conf.maintenance_mode:
print("Maintenance mode on for", s)

if frappe.local.conf.pause_scheduler:
print("Scheduler paused for", s)

if is_scheduler_inactive():
print("Scheduler inactive for", s)

frappe.destroy()

# TODO improve this


+ 1
- 1
frappe/utils/html_utils.py Прегледај датотеку

@@ -58,7 +58,7 @@ def sanitize_html(html, linkify=False):
return html

tags = (acceptable_elements + svg_elements + mathml_elements
+ ["html", "head", "meta", "link", "body", "iframe", "style", "o:p"])
+ ["html", "head", "meta", "link", "body", "style", "o:p"])
attributes = {"*": acceptable_attributes, 'svg': svg_attributes}
styles = bleach_whitelist.all_styles
strip_comments = False


+ 3
- 2
frappe/utils/jinja.py Прегледај датотеку

@@ -6,10 +6,11 @@ def get_jenv():
import frappe

if not getattr(frappe.local, 'jenv', None):
from jinja2 import Environment, DebugUndefined
from jinja2 import DebugUndefined
from jinja2.sandbox import SandboxedEnvironment

# frappe will be loaded last, so app templates will get precedence
jenv = Environment(loader = get_jloader(),
jenv = SandboxedEnvironment(loader = get_jloader(),
undefined=DebugUndefined)
set_filters(jenv)



+ 13
- 7
frappe/utils/scheduler.py Прегледај датотеку

@@ -79,14 +79,8 @@ def enqueue_events_for_site(site, queued_jobs):

try:
frappe.init(site=site)
if frappe.local.conf.maintenance_mode:
return

if frappe.local.conf.pause_scheduler:
return

frappe.connect()
if is_scheduler_disabled():
if is_scheduler_inactive():
return

enqueue_events(site=site, queued_jobs=queued_jobs)
@@ -226,6 +220,18 @@ def get_enabled_scheduler_events():
return ["all", "hourly", "hourly_long", "daily", "daily_long",
"weekly", "weekly_long", "monthly", "monthly_long", "cron"]

def is_scheduler_inactive():
if frappe.local.conf.maintenance_mode:
return True

if frappe.local.conf.pause_scheduler:
return True

if is_scheduler_disabled():
return True

return False

def is_scheduler_disabled():
if frappe.conf.disable_scheduler:
return True


+ 3
- 1
frappe/website/doctype/personal_data_download_request/personal_data_download_request.py Прегледај датотеку

@@ -12,7 +12,9 @@ from frappe.utils.verified_command import get_signed_params
class PersonalDataDownloadRequest(Document):
def after_insert(self):
personal_data = get_user_data(self.user)
self.generate_file_and_send_mail(personal_data)

frappe.enqueue_doc(self.doctype, self.name, 'generate_file_and_send_mail',
queue='short', personal_data=personal_data, now=frappe.flags.in_test)

def generate_file_and_send_mail(self, personal_data):
"""generate the file link for download"""


+ 15
- 8
frappe/website/doctype/personal_data_download_request/test_personal_data_download_request.py Прегледај датотеку

@@ -21,18 +21,25 @@ class TestRequestPersonalData(unittest.TestCase):

def test_file_and_email_creation(self):
frappe.set_user('test_privacy@example.com')
download_request = frappe.get_doc({"doctype": 'Personal Data Download Request', 'user': 'test_privacy@example.com'})
download_request = frappe.get_doc({
"doctype": 'Personal Data Download Request',
'user': 'test_privacy@example.com'
})
download_request.save(ignore_permissions=True)

frappe.set_user('Administrator')

f = frappe.get_all('File',
{'attached_to_doctype':'Personal Data Download Request', 'attached_to_name': download_request.name},
['*'])
self.assertEqual(len(f), 1)
file_count = frappe.db.count('File', {
'attached_to_doctype':'Personal Data Download Request',
'attached_to_name': download_request.name
})

self.assertEqual(file_count, 1)

email_queue = frappe.db.sql("""SELECT *
FROM `tabEmail Queue`
ORDER BY `creation` DESC""", as_dict=True)
email_queue = frappe.get_all('Email Queue',
fields=['message'],
order_by="creation DESC",
limit=1)
self.assertTrue("Subject: Download Your Data" in email_queue[0].message)

frappe.db.sql("delete from `tabEmail Queue`")


+ 1
- 1
frappe/www/login.html Прегледај датотеку

@@ -87,7 +87,7 @@
<span class="indicator blue" data-text="{{ _("Forgot Password") }}"></span></div>
<input type="email" id="forgot_email"
class="form-control" placeholder="{{ _('Email address') }}" required autofocus>
<button class="btn btn-sm btn-primary btn-block btn-forgot" type="submit">{{ _("Send Password") }}</button>
<button class="btn btn-sm btn-primary btn-block btn-forgot" type="submit">{{ _("Reset Password") }}</button>
</form>
</div>
<div class='form-footer'>


+ 6
- 1
frappe/www/sitemap.py Прегледај датотеку

@@ -15,7 +15,12 @@ base_template_path = "templates/www/sitemap.xml"

def get_context(context):
"""generate the sitemap XML"""
host = get_request_site_address()

# the site might be accessible from multiple host_names
# for e.g gadgets.erpnext.com and gadgetsinternational.com
# so it should be picked from the request
host = frappe.utils.get_host_name_from_request()

links = []
for route, page in iteritems(get_pages()):
if page.sitemap:


Loading…
Откажи
Сачувај