Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: release v15 beta #21970

Merged
merged 55 commits into from
Aug 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
8b7ed91
fix: Made Set Password Page Better
Jul 28, 2023
d0c1152
refactor: refactored the code
Jul 28, 2023
213d744
fix: better UX
Jul 30, 2023
25f7593
fix: added validation of (if old password === new password)
Jul 31, 2023
b3e3193
fix: center notes text in FileUploader
barredterra Aug 1, 2023
3621daf
fix: Compress bit more agressively
surajshetty3416 Aug 2, 2023
5ebe28b
feat: Add formatter for "File Size"
surajshetty3416 Aug 2, 2023
a7be8cc
Merge remote-tracking branch 'upstream' into fix-image-compression
surajshetty3416 Aug 2, 2023
672835d
fix: Show "View File" in the sidebar of file doc
surajshetty3416 Aug 2, 2023
67a32bd
fix: Set minimum resolution of image
surajshetty3416 Aug 2, 2023
0b5a24b
Merge pull request #21899 from surajshetty3416/fix-image-compression
surajshetty3416 Aug 2, 2023
2b56520
fix: added debounce for checking old and new password same or not
Aug 2, 2023
975c484
Merge pull request #21892 from barredterra/center-upload-notes
surajshetty3416 Aug 2, 2023
d41d8a5
feat: print all filters in report builder
barredterra Aug 2, 2023
b9cdee8
feat: german translations for printed filters
barredterra Aug 2, 2023
0b509b8
fix: add invalid filters for fieldtype "Float" (#21904)
barredterra Aug 2, 2023
d1c3877
fix: debounce form refresh from realtime events (#21905)
ankush Aug 2, 2023
fa73d5e
perf(dx): let developers know that they need to enable index on links…
barredterra Aug 3, 2023
bd3be66
refactor: one keyup event for all inputs
Aug 3, 2023
dc0a8c5
fix: keep privacy setting of attachments on amend (#21911)
barredterra Aug 3, 2023
1cd6c4e
fix: fixed on click function
Aug 3, 2023
c4230f8
fix: autoincr status per doctype (#21918)
ankush Aug 4, 2023
fd15ab5
fix: revert pg incompatible change
ankush Aug 4, 2023
8817c22
fix: filter schema name on mariadb
ankush Aug 4, 2023
881240e
fix(Workspace): Clear bootinfo cache when creating a new workspace
cogk Aug 4, 2023
011d21b
refactor: docshare get_users (#21924)
barredterra Aug 5, 2023
2ed85ca
refactor: check license names before sending text
ankush Aug 5, 2023
201be85
chore: remove dead code
ankush Aug 5, 2023
cc85d39
fix: only allow system manager to start backups
ankush Aug 5, 2023
1f5480b
chore: move permission check earlier
sagarvora Aug 5, 2023
0cced74
fix: add rate limiting and type hints for `add_feedback`
sagarvora Aug 5, 2023
4931c73
fix: only rate limit if `frappe.request` is set
sagarvora Aug 5, 2023
3f3821b
fix: dont use `form_dict` & `frappe.call`
sagarvora Aug 5, 2023
773cefe
test: specify `args` or `kwargs` instead of `frappe.form_dict`
sagarvora Aug 5, 2023
7aed89a
test: set request before verifying
sagarvora Aug 5, 2023
fd2efdb
chore: whitelisted typo (#21930)
michellealva Aug 5, 2023
2b96324
fix: rate limit for all HTTP methods (#21929)
sagarvora Aug 5, 2023
e588f2d
Merge pull request #21928 from resilient-tech/fix-rate-limiter
sagarvora Aug 5, 2023
4fae798
fix: check file permission before zipping (#21934)
barredterra Aug 6, 2023
5fce1a5
fix: validate fieldname in get_group_by_count (#21932)
barredterra Aug 6, 2023
a2b2998
fix(DX): Wrap print format errors (#21944)
ankush Aug 6, 2023
27426f7
chore: code cleanup
Aug 6, 2023
dbc61cc
fix: workflow help
ankush Aug 7, 2023
3f971f3
feat: Added Re-run in Console Button in Console Log Doctype (#21825)
RitvikSardana Aug 7, 2023
e877d92
test: set `request_ip` when testing `reset_password` (#21937)
sagarvora Aug 7, 2023
b385fae
test: use unique IP to prevent future conflict with other tests
sagarvora Aug 7, 2023
f6326b6
fix: check before deleting prepared report (#21950)
ankush Aug 7, 2023
49a9f53
feat: text editor and mentions for discussions (#21886)
pateljannat Aug 7, 2023
6ed6a3f
chore: minor fix
shariquerik Aug 7, 2023
eebbcd0
Merge pull request #21846 from RitvikSardana/develop-ritvik-better-se…
shariquerik Aug 7, 2023
f617100
chore: Translate repeat frecuency on sidebar (#21956)
ernestoruiz89 Aug 8, 2023
c3aaab3
fix(Web Form): translation of forwarding message (#21948)
barredterra Aug 8, 2023
76c6924
Merge pull request #21903 from barredterra/print-report-filters
ankush Aug 8, 2023
9b52718
Merge pull request #21895 from cogk/fix-clear-bootinfo-cache-on-works…
ankush Aug 8, 2023
59e1db7
fix: barcode scanner library path
ankush Aug 8, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 12 additions & 28 deletions cypress/integration/discussions.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ context("Discussions", () => {
.should("have.value", "Discussion from tests");

// Enter comment
cy.get(".modal .comment-field")
.type("This is a discussion from the cypress ui tests.")
.should("have.value", "This is a discussion from the cypress ui tests.");
cy.get(".modal .discussions-comment").type(
"This is a discussion from the cypress ui tests."
);

// Submit
cy.get(".modal .submit-discussion").click();
Expand All @@ -38,21 +38,16 @@ context("Discussions", () => {
"Discussion from tests"
);
cy.get(".discussion-on-page:visible").should("have.class", "show");
cy.get(".discussion-on-page:visible .reply-card .reply-text").should(
cy.get(".discussion-on-page:visible .reply-card .reply-text .ql-editor p").should(
"have.text",
"This is a discussion from the cypress ui tests.\n"
"This is a discussion from the cypress ui tests."
);
};

const reply_through_comment_box = () => {
cy.get(".discussion-form:visible .comment-field")
.type(
"This is a discussion from the cypress ui tests. \n\nThis comment was entered through the commentbox on the page."
)
.should(
"have.value",
"This is a discussion from the cypress ui tests. \n\nThis comment was entered through the commentbox on the page."
);
cy.get(".discussion-form:visible .discussions-comment").type(
"This is a discussion from the cypress ui tests. \n\nThis comment was entered through the commentbox on the page."
);

cy.get(".discussion-form:visible .submit-discussion").click();
cy.wait(3000);
Expand All @@ -63,28 +58,18 @@ context("Discussions", () => {
.find(".reply-text")
.should(
"have.text",
"This is a discussion from the cypress ui tests. \n\nThis comment was entered through the commentbox on the page.\n"
"This is a discussion from the cypress ui tests. This comment was entered through the commentbox on the page.\n"
);
};

const cancel_and_clear_comment_box = () => {
cy.get(".discussion-form:visible .comment-field")
.type("This is a discussion from the cypress ui tests.")
.should("have.value", "This is a discussion from the cypress ui tests.");

cy.get(".discussion-form:visible .cancel-comment").click();
cy.get(".discussion-form:visible .comment-field").should("have.value", "");
};

const single_thread_discussion = () => {
cy.visit("/test-single-thread");
cy.get(".discussions-sidebar").should("have.length", 0);
cy.get(".reply").should("have.length", 0);

cy.get(".discussion-form:visible .comment-field")
.type("This comment is being made on a single thread discussion.")
.should("have.value", "This comment is being made on a single thread discussion.");

cy.get(".discussion-form:visible .discussions-comment").type(
"This comment is being made on a single thread discussion."
);
cy.get(".discussion-form:visible .submit-discussion").click();
cy.wait(3000);
cy.get(".discussion-on-page")
Expand All @@ -96,6 +81,5 @@ context("Discussions", () => {

it("reply through modal", reply_through_modal);
it("reply through comment box", reply_through_comment_box);
it("cancel and clear comment box", cancel_and_clear_comment_box);
it("single thread discussion", single_thread_discussion);
});
84 changes: 37 additions & 47 deletions frappe/core/doctype/comment/test_comment.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,6 @@


class TestComment(FrappeTestCase):
def tearDown(self):
frappe.form_dict.comment = None
frappe.form_dict.comment_email = None
frappe.form_dict.comment_by = None
frappe.form_dict.reference_doctype = None
frappe.form_dict.reference_name = None
frappe.form_dict.route = None
frappe.local.request_ip = None

def test_comment_creation(self):
test_doc = frappe.get_doc(dict(doctype="ToDo", description="test"))
test_doc.insert()
Expand All @@ -45,16 +36,15 @@ def test_public_comment(self):
test_blog = make_test_blog()

frappe.db.delete("Comment", {"reference_doctype": "Blog Post"})

frappe.form_dict.comment = "Good comment with 10 chars"
frappe.form_dict.comment_email = "test@test.com"
frappe.form_dict.comment_by = "Good Tester"
frappe.form_dict.reference_doctype = "Blog Post"
frappe.form_dict.reference_name = test_blog.name
frappe.form_dict.route = test_blog.route
frappe.local.request_ip = "127.0.0.1"

add_comment()
add_comment_args = {
"comment": "Good comment with 10 chars",
"comment_email": "test@test.com",
"comment_by": "Good Tester",
"reference_doctype": test_blog.doctype,
"reference_name": test_blog.name,
"route": test_blog.route,
}
add_comment(**add_comment_args)

self.assertEqual(
frappe.get_all(
Expand All @@ -67,10 +57,10 @@ def test_public_comment(self):

frappe.db.delete("Comment", {"reference_doctype": "Blog Post"})

frappe.form_dict.comment = "pleez vizits my site http://mysite.com"
frappe.form_dict.comment_by = "bad commentor"

add_comment()
add_comment_args.update(
comment="pleez vizits my site http://mysite.com", comment_by="bad commentor"
)
add_comment(**add_comment_args)

self.assertEqual(
len(
Expand All @@ -86,11 +76,8 @@ def test_public_comment(self):
# test for filtering html and css injection elements
frappe.db.delete("Comment", {"reference_doctype": "Blog Post"})

frappe.form_dict.comment = "<script>alert(1)</script>Comment"
frappe.form_dict.comment_by = "hacker"

add_comment()

add_comment_args.update(comment="<script>alert(1)</script>Comment", comment_by="hacker")
add_comment(**add_comment_args)
self.assertEqual(
frappe.get_all(
"Comment",
Expand All @@ -106,27 +93,30 @@ def test_public_comment(self):
def test_guest_cannot_comment(self):
test_blog = make_test_blog()
with set_user("Guest"):
frappe.form_dict.comment = "Good comment with 10 chars"
frappe.form_dict.comment_email = "mail@example.org"
frappe.form_dict.comment_by = "Good Tester"
frappe.form_dict.reference_doctype = "Blog Post"
frappe.form_dict.reference_name = test_blog.name
frappe.form_dict.route = test_blog.route
frappe.local.request_ip = "127.0.0.1"

self.assertEqual(add_comment(), None)
self.assertEqual(
add_comment(
comment="Good comment with 10 chars",
comment_email="mail@example.org",
comment_by="Good Tester",
reference_doctype="Blog Post",
reference_name=test_blog.name,
route=test_blog.route,
),
None,
)

def test_user_not_logged_in(self):
some_system_user = frappe.db.get_value("User", {})
some_system_user = frappe.db.get_value("User", {"name": ("not in", frappe.STANDARD_USERS)})

test_blog = make_test_blog()
with set_user("Guest"):
frappe.form_dict.comment = "Good comment with 10 chars"
frappe.form_dict.comment_email = some_system_user
frappe.form_dict.comment_by = "Good Tester"
frappe.form_dict.reference_doctype = "Blog Post"
frappe.form_dict.reference_name = test_blog.name
frappe.form_dict.route = test_blog.route
frappe.local.request_ip = "127.0.0.1"

self.assertRaises(frappe.ValidationError, add_comment)
self.assertRaises(
frappe.ValidationError,
add_comment,
comment="Good comment with 10 chars",
comment_email=some_system_user,
comment_by="Good Tester",
reference_doctype="Blog Post",
reference_name=test_blog.name,
route=test_blog.route,
)
20 changes: 19 additions & 1 deletion frappe/core/doctype/doctype/doctype.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
from frappe.modules import get_doc_path, make_boilerplate
from frappe.modules.import_file import get_file_path
from frappe.query_builder.functions import Concat
from frappe.utils import cint, flt, random_string
from frappe.utils import cint, flt, get_table_name, random_string
from frappe.website.utils import clear_cache

if TYPE_CHECKING:
Expand Down Expand Up @@ -198,6 +198,7 @@ def validate(self):
self.set("can_change_name_type", validate_autoincrement_autoname(self))
self.validate_document_type()
validate_fields(self)
self.check_indexing_for_dashboard_links()

if not self.istable:
validate_permissions(self)
Expand Down Expand Up @@ -298,6 +299,23 @@ def set_default_translatable(self):
if d.translatable and not supports_translation(d.fieldtype):
d.translatable = 0

def check_indexing_for_dashboard_links(self):
"""Enable indexing for outgoing links used in dashboard"""
for d in self.fields:
if d.fieldtype == "Link" and not (d.unique or d.search_index):
referred_as_link = frappe.db.exists(
"DocType Link",
{"parent": d.options, "link_doctype": self.name, "link_fieldname": d.fieldname},
)
if not referred_as_link:
continue

frappe.msgprint(
_("{0} should be indexed because it's referred in dashboard connections").format(_(d.label)),
alert=True,
indicator="orange",
)

def check_developer_mode(self):
"""Throw exception if not developer mode or via patch"""
if frappe.flags.in_patch or frappe.flags.in_test:
Expand Down
3 changes: 3 additions & 0 deletions frappe/core/doctype/file/file.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ frappe.ui.form.on("File", {
if (frm.doc.file_name && frm.doc.file_name.split(".").splice(-1)[0] === "zip") {
frm.add_custom_button(__("Unzip"), () => frm.trigger("unzip"));
}
if (frm.doc.file_url) {
frm.add_web_link(frm.doc.file_url, __("View file"));
}
},

preview_file: function (frm) {
Expand Down
3 changes: 2 additions & 1 deletion frappe/core/doctype/file/file.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
"in_list_view": 1,
"label": "File Size",
"length": 20,
"options": "File Size",
"read_only": 1
},
{
Expand Down Expand Up @@ -174,7 +175,7 @@
"icon": "fa fa-file",
"idx": 1,
"links": [],
"modified": "2023-05-02 15:42:14.274901",
"modified": "2023-08-02 09:43:51.178011",
"modified_by": "Administrator",
"module": "Core",
"name": "File",
Expand Down
2 changes: 2 additions & 0 deletions frappe/core/doctype/file/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -734,6 +734,8 @@ def zip_files(files):
continue
if _file.is_folder:
continue
if not has_permission(_file, "read"):
continue
zf.writestr(_file.file_name, _file.get_content())
zf.close()
return zip_file.getvalue()
Expand Down
13 changes: 10 additions & 3 deletions frappe/core/doctype/package/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
import frappe
from frappe.model.document import Document

LICENSES = (
"GNU Affero General Public License",
"GNU General Public License",
"MIT License",
)


class Package(Document):
# begin: auto-generated types
Expand All @@ -29,6 +35,7 @@ def validate(self):


@frappe.whitelist()
def get_license_text(license_type):
with open(os.path.join(os.path.dirname(__file__), "licenses", license_type + ".md")) as textfile:
return textfile.read()
def get_license_text(license_type: str) -> str | None:
if license_type in LICENSES:
with open(os.path.join(os.path.dirname(__file__), "licenses", license_type + ".md")) as textfile:
return textfile.read()
6 changes: 3 additions & 3 deletions frappe/core/doctype/prepared_report/prepared_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -211,9 +211,9 @@ def expire_stalled_report():
def delete_prepared_reports(reports):
reports = frappe.parse_json(reports)
for report in reports:
frappe.delete_doc(
"Prepared Report", report["name"], ignore_permissions=True, delete_permanently=True
)
prepared_report = frappe.get_doc("Prepared Report", report["name"])
if prepared_report.has_permission():
prepared_report.delete(ignore_permissions=True, delete_permanently=True)


def create_json_gz_file(data, dt, dn):
Expand Down
3 changes: 3 additions & 0 deletions frappe/core/doctype/user/test_user.py
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,9 @@ def test_reset_password(self):
set_request(path="/random")
frappe.local.cookie_manager = CookieManager()
frappe.local.login_manager = LoginManager()
# used by rate limiter when calling reset_password
frappe.local.request_ip = "127.0.0.69"
frappe.db.set_single_value("System Settings", "password_reset_limit", 6)

frappe.set_user("testpassword@example.com")
test_user = frappe.get_doc("User", "testpassword@example.com")
Expand Down
2 changes: 1 addition & 1 deletion frappe/core/doctype/user/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -1010,7 +1010,7 @@ def sign_up(email: str, full_name: str, redirect_to: str) -> tuple[int, str]:


@frappe.whitelist(allow_guest=True)
@rate_limit(limit=get_password_reset_limit, seconds=24 * 60 * 60, methods=["POST"])
@rate_limit(limit=get_password_reset_limit, seconds=24 * 60 * 60)
def reset_password(user: str) -> str:
if user == "Administrator":
return "not allowed"
Expand Down
9 changes: 7 additions & 2 deletions frappe/desk/doctype/console_log/console_log.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
// For license information, please see license.txt

frappe.ui.form.on("Console Log", {
// refresh: function(frm) {
// }
refresh: function (frm) {
frm.add_custom_button(__("Re-Run in Console"), () => {
localStorage.setItem("system_console_code", frm.doc.script);
localStorage.setItem("system_console_type", frm.doc.type);
frappe.set_route("Form", "System Console");
});
},
});
12 changes: 10 additions & 2 deletions frappe/desk/doctype/console_log/console_log.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"script"
"script",
"type"
],
"fields": [
{
Expand All @@ -15,11 +16,18 @@
"in_list_view": 1,
"label": "Script",
"read_only": 1
},
{
"fieldname": "type",
"fieldtype": "Data",
"hidden": 1,
"label": "Type",
"read_only": 1
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2023-07-05 22:16:02.823955",
"modified": "2023-07-27 22:52:37.239039",
"modified_by": "Administrator",
"module": "Desk",
"name": "Console Log",
Expand Down
1 change: 1 addition & 0 deletions frappe/desk/doctype/console_log/console_log.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ class ConsoleLog(Document):
from frappe.types import DF

script: DF.Code | None
type: DF.Data | None
# end: auto-generated types
pass
Loading
Loading