From 1bdda7a803d0a057dcc62f1b85a624a0af5634b8 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Fri, 1 May 2026 13:20:13 +0530 Subject: [PATCH 1/2] fix: Avoid suggesting invalid `" "` as default app --- frappe/core/doctype/system_settings/system_settings.js | 2 +- frappe/core/doctype/user/user.js | 2 +- frappe/core/doctype/user/user_list.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/frappe/core/doctype/system_settings/system_settings.js b/frappe/core/doctype/system_settings/system_settings.js index e69470861a..c5135b7477 100644 --- a/frappe/core/doctype/system_settings/system_settings.js +++ b/frappe/core/doctype/system_settings/system_settings.js @@ -19,7 +19,7 @@ frappe.ui.form.on("System Settings", { frappe.xcall("frappe.apps.get_apps").then((r) => { let apps = r?.map((r) => r.name) || []; - frm.set_df_property("default_app", "options", [" ", ...apps]); + frm.set_df_property("default_app", "options", ["", ...apps]); }); frm.trigger("set_rounding_method_options"); diff --git a/frappe/core/doctype/user/user.js b/frappe/core/doctype/user/user.js index f507eaf377..10c23fc042 100644 --- a/frappe/core/doctype/user/user.js +++ b/frappe/core/doctype/user/user.js @@ -105,7 +105,7 @@ frappe.ui.form.on("User", { frappe.xcall("frappe.apps.get_apps").then((r) => { let apps = r?.map((r) => r.name) || []; - frm.set_df_property("default_app", "options", [" ", ...apps]); + frm.set_df_property("default_app", "options", ["", ...apps]); }); if (frm.is_new()) { diff --git a/frappe/core/doctype/user/user_list.js b/frappe/core/doctype/user/user_list.js index d0688f7b83..20f4e50332 100644 --- a/frappe/core/doctype/user/user_list.js +++ b/frappe/core/doctype/user/user_list.js @@ -23,7 +23,7 @@ frappe.listview_settings["User"] = { frappe.xcall("frappe.apps.get_apps").then((r) => { let apps = r?.map((r) => r.name) || []; - default_app_field.options = [" ", ...apps].join("\n"); + default_app_field.options = ["", ...apps].join("\n"); }); }, }; From d9f8b248536c0fd9b9bc45c488c2dc02888cd402 Mon Sep 17 00:00:00 2001 From: Ankush Menat Date: Fri, 1 May 2026 13:25:54 +0530 Subject: [PATCH 2/2] fix: Erase invalid default apps and ignore at runtime in /apps handlers --- frappe/apps.py | 5 +++++ frappe/core/doctype/user/test_user.py | 15 +++++++++++++++ frappe/core/doctype/user/user.py | 3 +++ 3 files changed, 23 insertions(+) diff --git a/frappe/apps.py b/frappe/apps.py index 0dd30b4340..fdbb5c74f3 100644 --- a/frappe/apps.py +++ b/frappe/apps.py @@ -53,6 +53,8 @@ def get_apps(): def get_route(app_name): + if app_name not in frappe.get_installed_apps(): + return "/apps" # Invalid defaults apps = frappe.get_hooks("add_to_apps_screen", app_name=app_name) app = next((app for app in apps if app.get("name") == app_name), None) return app.get("route") if app and app.get("route") else "/apps" @@ -89,6 +91,9 @@ def get_default_path(): @frappe.whitelist() def set_app_as_default(app_name: str): + if app_name not in frappe.get_installed_apps(): + frappe.throw(_("App {} is not installed").format(frappe.bold(app_name))) + if frappe.db.get_value("User", frappe.session.user, "default_app") == app_name: frappe.db.set_value("User", frappe.session.user, "default_app", "") else: diff --git a/frappe/core/doctype/user/test_user.py b/frappe/core/doctype/user/test_user.py index a091eeff2e..f6ee4ac838 100644 --- a/frappe/core/doctype/user/test_user.py +++ b/frappe/core/doctype/user/test_user.py @@ -466,6 +466,21 @@ class TestUser(IntegrationTestCase): sorted(m.get("module_name") for m in get_modules_from_all_apps()), ) + def test_default_app(self): + from frappe.apps import get_default_path + + with test_user(roles=["System Manager"]) as user: + user.default_app = "next_erp" + user.save() + self.assertFalse(user.default_app) + + frappe.set_user(user.name) + user.db_set("default_app", "next_erp") + user.reload() + self.assertTrue(user.default_app) + + get_default_path() # defaults will also trigger hooks logic + @IntegrationTestCase.change_settings("System Settings", reset_password_link_expiry_duration=1) def test_reset_password_link_expiry(self): new_password = "new_password" diff --git a/frappe/core/doctype/user/user.py b/frappe/core/doctype/user/user.py index d62c68dc82..2e5adfb0f9 100644 --- a/frappe/core/doctype/user/user.py +++ b/frappe/core/doctype/user/user.py @@ -248,6 +248,9 @@ class User(Document): if self.language == "Loading...": self.language = None + if self.default_app and self.default_app not in frappe.get_installed_apps(): + self.default_app = "" + if (self.name not in ["Administrator", "Guest"]) and (not self.get_social_login_userid("frappe")): self.set_social_login_userid("frappe", frappe.generate_hash(length=39))