Commit de1037b6 authored by mbauskar's avatar mbauskar
Browse files

Merge branch 'hotfix'

parents 52d7d7af 165b59cd
Showing with 92 additions and 105 deletions
+92 -105
......@@ -14,7 +14,7 @@ import os, sys, importlib, inspect, json
from .exceptions import *
from .utils.jinja import get_jenv, get_template, render_template, get_email_from_template
__version__ = '9.1.7'
__version__ = '9.1.8'
__title__ = "Frappe Framework"
local = Local()
......
......@@ -57,7 +57,7 @@ def get_value(doctype, fieldname, filters=None, as_dict=True, debug=False):
:param filters: dict or string for identifying the record'''
if not frappe.has_permission(doctype):
frappe.throw(_("Not permitted"), frappe.PermissionError)
frappe.throw(_("No permission for {0}".format(doctype)), frappe.PermissionError)
try:
filters = json.loads(filters)
......
......@@ -129,36 +129,6 @@
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "sms_sender_name",
"fieldtype": "Data",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "SMS Sender Name",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_on_submit": 0,
......@@ -231,8 +201,8 @@
"issingle": 1,
"istable": 0,
"max_attachments": 0,
"modified": "2017-07-22 22:52:16.066981",
"modified_by": "chude.osiegbu@manqala.com",
"modified": "2017-10-17 14:30:41.503586",
"modified_by": "Administrator",
"module": "Core",
"name": "SMS Settings",
"owner": "Administrator",
......
......@@ -28,18 +28,6 @@ def validate_receiver_nos(receiver_list):
return validated_receiver_list
def get_sender_name():
"returns name as SMS sender"
sender_name = frappe.db.get_single_value('SMS Settings', 'sms_sender_name') or \
'ERPNXT'
if len(sender_name) > 6 and \
frappe.db.get_default("country") == "India":
throw("""As per TRAI rule, sender name must be exactly 6 characters.
Kindly change sender name in Setup --> Global Defaults.
Note: Hyphen, space, numeric digit, special characters are not allowed.""")
return sender_name
@frappe.whitelist()
def get_contact_number(contact_name, ref_doctype, ref_name):
"returns mobile number of the contact"
......@@ -66,7 +54,6 @@ def send_sms(receiver_list, msg, sender_name = '', success_msg = True):
arg = {
'receiver_list' : receiver_list,
'message' : unicode(msg).encode('utf-8'),
'sender_name' : sender_name or get_sender_name(),
'success_msg' : success_msg
}
......@@ -107,7 +94,6 @@ def send_request(gateway_url, params):
# =========================================================
def create_sms_log(args, sent_to):
sl = frappe.new_doc('SMS Log')
sl.sender_name = args['sender_name']
sl.sent_on = nowdate()
sl.message = args['message'].decode('utf-8')
sl.no_of_requested_sms = len(args['receiver_list'])
......
# -*- coding: utf-8 -*-
# Copyright (c) 2017, Frappe Technologies and Contributors
# See license.txt
from __future__ import unicode_literals
import frappe
import unittest
class TestSMSSettings(unittest.TestCase):
pass
......@@ -7,8 +7,8 @@ frappe.patches.v7_1.rename_scheduler_log_to_error_log
frappe.patches.v6_1.rename_file_data
frappe.patches.v7_0.re_route #2016-06-27
frappe.patches.v7_2.remove_in_filter
execute:frappe.reload_doc('core', 'doctype', 'doctype', force=True) #2017-03-09
frappe.patches.v8_0.drop_in_dialog
execute:frappe.reload_doc('core', 'doctype', 'doctype', force=True) #2017-03-09
execute:frappe.reload_doc('core', 'doctype', 'docfield', force=True) #2017-03-03
execute:frappe.reload_doc('core', 'doctype', 'docperm') #2017-03-03
frappe.patches.v8_0.drop_is_custom_from_docperm
......@@ -191,6 +191,6 @@ frappe.patches.v8_1.delete_custom_docperm_if_doctype_not_exists
frappe.patches.v8_5.delete_email_group_member_with_invalid_emails
frappe.patches.v8_x.update_user_permission
frappe.patches.v8_5.patch_event_colors
frappe.patches.v8_7.update_email_queue_status
frappe.patches.v8_10.delete_static_web_page_from_global_search
frappe.patches.v8_x.add_bgn_xaf_xof_currencies
frappe.patches.v9_1.add_sms_sender_name_as_parameters
\ No newline at end of file
from __future__ import unicode_literals
import frappe
from frappe.email.smtp import get_default_outgoing_email_account
def execute():
# set the email queue status to Not Sent if google_analytics_id is UA-8911157-19
default_email_account = get_default_outgoing_email_account()
if frappe.conf.get("google_analytics_id") == "UA-8911157-19" or \
(default_email_account and default_email_account.email_id == "notifications@erpnext.com"):
frappe.db.sql("""update `tabEmail Queue` set status='Not Sent' where
creation>=DATE_SUB(NOW(), INTERVAL 16 HOUR)""")
\ No newline at end of file
from __future__ import unicode_literals
# Copyright (c) 2017, Frappe and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
def execute():
sms_sender_name = frappe.db.get_single_value("SMS Settings", "sms_sender_name")
if sms_sender_name:
frappe.reload_doctype("SMS Settings")
sms_settings = frappe.get_doc("SMS Settings")
sms_settings.append("parameters", {
"parameter": "sender_name",
"value": sms_sender_name
})
sms_settings.save()
\ No newline at end of file
......@@ -2,9 +2,6 @@ frappe.ui.form.ControlHTML = frappe.ui.form.Control.extend({
make: function() {
this._super();
this.disp_area = this.wrapper;
$(document).on('change', () => {
setTimeout(() => this.refresh_input(), 500);
});
},
refresh_input: function() {
var content = this.get_content();
......
......@@ -259,6 +259,7 @@ frappe.ui.form.ControlTextEditor = frappe.ui.form.ControlCode.extend({
max_width: this.df.max_width,
max_height: this.df.max_height,
options: "Image",
no_socketio: true,
btn: this.image_dialog.set_primary_action(__("Insert")),
on_no_attach: function() {
// if no attachmemts,
......
......@@ -10,7 +10,9 @@ from frappe import _
def test_password_strength(password, user_inputs=None):
'''Wrapper around zxcvbn.password_strength'''
result = zxcvbn(password, user_inputs)
result['feedback'] = get_feedback(result['score'], result['sequence'])
result.update({
"feedback": get_feedback(result.get('score'), result.get('sequence'))
})
return result
# NOTE: code modified for frappe translations
......@@ -33,23 +35,27 @@ default_feedback = {
],
}
def get_feedback (score, sequence):
def get_feedback(score, sequence):
"""
Returns the feedback dictionary consisting of ("warning","suggestions") for the given sequences.
"""
minimum_password_score = int(frappe.db.get_single_value("System Settings", "minimum_password_score"))
global default_feedback
minimum_password_score = int(frappe.db.get_single_value("System Settings", "minimum_password_score") or 2)
# Starting feedback
if len(sequence) == 0:
return default_feedback
# No feedback if score is good or great
if score >= minimum_password_score:
return dict({"warning": "","suggestions": []})
return dict({"warning": "", "suggestions": []})
# Tie feedback to the longest match for longer sequences
longest_match = max(sequence, key=lambda x: len(x['token']))
longest_match = max(sequence, key=lambda seq: len(seq.get('token', '')))
# Get feedback for this match
feedback = get_match_feedback(longest_match, len(sequence) == 1)
# If no concrete feedback returned, give more general feedback
if not feedback:
feedback = {
......@@ -64,50 +70,55 @@ def get_match_feedback(match, is_sole_match):
"""
Returns feedback as a dictionary for a certain match
"""
# Define a number of functions that are used in a look up dictionary
def fun_bruteforce():
# Define a number of functions that are used in a look up dictionary
return None
def fun_dictionary():
# If the match is of type dictionary, call specific function
return get_dictionary_match_feedback(match, is_sole_match)
def fun_spatial():
if match["turns"] == 1:
feedback ={
feedback = {
"warning": _('Short keyboard patterns are easy to guess'),
"suggestions":[
_("Make use of longer keyboard patterns")
],
}
if match.get("turns") == 1:
feedback = {
"warning": _('Straight rows of keys are easy to guess'),
"suggestions":[
_("Try to use a longer keyboard pattern with more turns")
],
}
else:
feedback ={
"warning": _('Short keyboard patterns are easy to guess'),
"suggestions":[
_("Make use of longer keyboard patterns")
],
}
return feedback
def fun_repeat():
feedback ={
"warning": _('Repeats like "abcabcabc" are only slightly harder to guess than "abc"'),
"suggestions":[
_("Try to avoid repeated words and characters")
],
}
if len(match["repeated_char"]) == 1:
feedback ={
feedback = {
"warning": _('Repeats like "aaa" are easy to guess'),
"suggestions":[
_("Let's avoid repeated words and characters")
],
}
else:
feedback ={
"warning": _('Repeats like "abcabcabc" are only slightly harder to guess than "abc"'),
"suggestions":[
_("Try to avoid repeated words and characters")
],
}
return feedback
def fun_sequence():
return {
"suggestions":[
_("Avoid sequences like abc or 6543 as they are easy to guess")
],
}
def fun_regex():
if match["regex_name"] == "recent_year":
return {
......@@ -117,6 +128,7 @@ def get_match_feedback(match, is_sole_match):
_("Avoid years that are associated with you.")
],
}
def fun_date():
return {
"warning": _("Dates are often easy to guess."),
......@@ -138,7 +150,7 @@ def get_match_feedback(match, is_sole_match):
}
pattern_fn = patterns.get(match['pattern'])
if pattern_fn:
return(pattern_fn())
return (pattern_fn())
def get_dictionary_match_feedback(match, is_sole_match):
"""
......@@ -146,35 +158,43 @@ def get_dictionary_match_feedback(match, is_sole_match):
"""
warning = ""
suggestions = []
# If the match is a common password
if match["dictionary_name"] == "passwords":
if is_sole_match and not match["l33t_entropy"]:
if match["rank"] <= 10:
if match.get("dictionary_name") == "passwords":
if is_sole_match and not match.get("l33t_entropy"):
if match.get("rank") <= 10:
warning = _("This is a top-10 common password.")
elif match["rank"] <= 100:
elif match.get("rank") <= 100:
warning = _("This is a top-100 common password.")
else:
warning = _("This is a very common password.")
else:
warning = _("This is similar to a commonly used password.")
# If the match is a common english word
elif match["dictionary_name"] == "english":
elif match.get("dictionary_name") == "english":
if is_sole_match:
warning = _("A word by itself is easy to guess.")
# If the match is a common surname/name
elif match["dictionary_name"] in ["surnames", "male_names", "female_names"]:
elif match.get("dictionary_name") in ["surnames", "male_names", "female_names"]:
if is_sole_match:
warning = _("Names and surnames by themselves are easy to guess.")
else:
warning = _("Common names and surnames are easy to guess.")
word = match["token"]
word = match.get("token")
# Variations of the match like UPPERCASES
if re.match(scoring.START_UPPER, word):
suggestions.append(_("Capitalization doesn't help very much."))
elif re.match(scoring.ALL_UPPER, word):
suggestions.append(_("All-uppercase is almost as easy to guess as all-lowercase."))
# Match contains l33t speak substitutions
if match["l33t_entropy"]:
if match.get("l33t_entropy"):
suggestions.append(_("Predictable substitutions like '@' instead of 'a' don't help very much."))
return {"warning": warning, "suggestions": suggestions}
return {
"warning": warning,
"suggestions": suggestions
}
......@@ -80,7 +80,7 @@ def is_static_file(path):
if ('.' not in path):
return False
extn = path.rsplit('.', 1)[-1]
if extn in ('html', 'md', 'js', 'xml', 'css'):
if extn in ('html', 'md', 'js', 'xml', 'css', 'txt'):
return False
for app in frappe.get_installed_apps():
......@@ -101,7 +101,6 @@ def get_static_file_reponse():
response.mimetype = mimetypes.guess_type(frappe.flags.file_path)[0] or b'application/octet-stream'
return response
def build_response(path, data, http_status_code, headers=None):
# build response
response = Response()
......
......@@ -4,8 +4,8 @@ no_sitemap = 1
base_template_path = "templates/www/robots.txt"
def get_context(context):
robots_txt = (frappe.db.get_single_value('Website Settings', 'robots_txt')
or (frappe.local.conf.robots_txt and frappe.read_file(frappe.local.conf.robots_txt))
or '')
robots_txt = (
frappe.db.get_single_value('Website Settings', 'robots_txt') or
(frappe.local.conf.robots_txt and frappe.read_file(frappe.local.conf.robots_txt)) or '')
return { 'robots_txt': robots_txt }
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