From 2cf3816288779b4d4b17a25f9b84cdda70b39e0a Mon Sep 17 00:00:00 2001 From: Andrew Date: Wed, 24 Sep 2025 20:36:41 -0400 Subject: [PATCH 1/8] Refactor users validators to only have one robust error --- app/classes/controllers/users_controller.py | 6 +----- app/classes/web/routes/api/users/index.py | 7 ++++++- app/translations/en_EN.json | 3 +-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/classes/controllers/users_controller.py b/app/classes/controllers/users_controller.py index 64522c97..63443852 100644 --- a/app/classes/controllers/users_controller.py +++ b/app/classes/controllers/users_controller.py @@ -65,11 +65,7 @@ class UsersController: "pattern": "(?=.*[^0-9])", "examples": ["crafty"], "title": "Password", - "error": { - "minLength": "passLength", - "type": "numbericPassword", - "pattern": "numbericPassword", - }, + "error": "passProp", }, "email": { "type": "string", diff --git a/app/classes/web/routes/api/users/index.py b/app/classes/web/routes/api/users/index.py index fc9fcc4f..de21cf10 100644 --- a/app/classes/web/routes/api/users/index.py +++ b/app/classes/web/routes/api/users/index.py @@ -101,9 +101,14 @@ class ApiUsersIndexHandler(BaseApiHandler): offending_key = "" if why.schema.get("fill", None): offending_key = why.path[0] if why.path else None + schema_error = why.schema.get("error", "additionalProperties") + # We need to get the type of this for additional password property errors + translate_key = schema_error + if isinstance(schema_error, dict): + translate_key = schema_error[why.validator] err = f"""{offending_key} {self.translator.translate( "validators", - why.schema.get("error", "additionalProperties")[why.validator], + translate_key, self.controller.users.get_user_lang_by_id(auth_data[4]["user_id"]), )} {why.schema.get("enum", "")}""" return self.finish_json( diff --git a/app/translations/en_EN.json b/app/translations/en_EN.json index b05e457e..3e65cc60 100644 --- a/app/translations/en_EN.json +++ b/app/translations/en_EN.json @@ -763,8 +763,7 @@ "filesPageLen": "length must be greater than 1 for property", "insufficientPerms": "Permission Error: Missing permissions for this resource", "mfaName": "Input must be of type string and a minimum of 3 characters for property", - "passLength": "Password Too Short. Minimum Length: 8", - "numbericPassword": "Numeric Password. Needs at least 1 alphabetic character", + "passProp": "Password must be a string with a min length of 8 characters.", "roleManager": "Role manager must be of type integer (manager ID) or None", "roleName": "Role name must be a string that is greater than 1 character. It must not include any of the following symbols: [ ] , ", "roleServerId": "Server ID property must be a string with a minimum length of 1", -- GitLab From dd3a3fa5dd6b34084b883e0fe78b8df1cc719c9e Mon Sep 17 00:00:00 2001 From: Andrew Date: Wed, 24 Sep 2025 20:36:56 -0400 Subject: [PATCH 2/8] Allow numeric password --- app/frontend/static/assets/js/shared/userSettings.js | 2 +- app/frontend/templates/panel/panel_edit_user.html | 7 +++++-- app/frontend/templates/public/login.html | 4 ++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/frontend/static/assets/js/shared/userSettings.js b/app/frontend/static/assets/js/shared/userSettings.js index 841754e9..4216a93c 100644 --- a/app/frontend/static/assets/js/shared/userSettings.js +++ b/app/frontend/static/assets/js/shared/userSettings.js @@ -44,7 +44,7 @@ $(".edit_password").on("click", async function () { headers: { 'X-XSRFToken': token }, - body: JSON.stringify({ "password": password }), + body: JSON.stringify({ "password": toString(password) }), }); let responseData = await res.json(); if (responseData.status === "ok") { diff --git a/app/frontend/templates/panel/panel_edit_user.html b/app/frontend/templates/panel/panel_edit_user.html index 79feb54e..25575fb7 100644 --- a/app/frontend/templates/panel/panel_edit_user.html +++ b/app/frontend/templates/panel/panel_edit_user.html @@ -410,10 +410,13 @@ data['lang']) }}{% end %} } } function replacer(key, value) { - if (typeof value == "boolean" || key === "email" || key === "permissions" || key === "roles" || key === "password") { + if (typeof value == "boolean" || key === "email" || key === "permissions" || key === "roles") { console.log(key) return value - } else { + } else if (key === "password"){ + return toString(value) + } + else { console.log(key, value) return (isNaN(value) ? value : +value); } diff --git a/app/frontend/templates/public/login.html b/app/frontend/templates/public/login.html index e11ffb58..d6b06c22 100644 --- a/app/frontend/templates/public/login.html +++ b/app/frontend/templates/public/login.html @@ -182,13 +182,13 @@ let formDataObject = Object.fromEntries(formData.entries()); let body = { "username": formDataObject.username, - "password": formDataObject.password, + "password": toString(formDataObject.password), } if (formDataObject.totp != "") { let key = $("#2fa-type").val(); body = { "username": formDataObject.username, - "password": formDataObject.password, + "password": toString(formDataObject.password), [key]: formDataObject.totp, } } -- GitLab From ca6925bb69a72e661234e615023a06f2a95b745a Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 26 Sep 2025 12:51:19 -0700 Subject: [PATCH 3/8] Allow user password to be all numeric --- app/classes/controllers/users_controller.py | 2 +- app/frontend/templates/panel/panel_edit_user.html | 3 ++- app/frontend/templates/public/login.html | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app/classes/controllers/users_controller.py b/app/classes/controllers/users_controller.py index 63443852..77aa2500 100644 --- a/app/classes/controllers/users_controller.py +++ b/app/classes/controllers/users_controller.py @@ -62,7 +62,7 @@ class UsersController: "password": { "type": "string", "minLength": self.helper.minimum_password_length, - "pattern": "(?=.*[^0-9])", + "pattern": "^.{8,}$", "examples": ["crafty"], "title": "Password", "error": "passProp", diff --git a/app/frontend/templates/panel/panel_edit_user.html b/app/frontend/templates/panel/panel_edit_user.html index 25575fb7..c8fd09a6 100644 --- a/app/frontend/templates/panel/panel_edit_user.html +++ b/app/frontend/templates/panel/panel_edit_user.html @@ -414,7 +414,8 @@ data['lang']) }}{% end %} console.log(key) return value } else if (key === "password"){ - return toString(value) + value = value.toString() + return value } else { console.log(key, value) diff --git a/app/frontend/templates/public/login.html b/app/frontend/templates/public/login.html index d6b06c22..ea0f46c2 100644 --- a/app/frontend/templates/public/login.html +++ b/app/frontend/templates/public/login.html @@ -182,13 +182,13 @@ let formDataObject = Object.fromEntries(formData.entries()); let body = { "username": formDataObject.username, - "password": toString(formDataObject.password), + "password": (formDataObject.password).toString(), } if (formDataObject.totp != "") { let key = $("#2fa-type").val(); body = { "username": formDataObject.username, - "password": toString(formDataObject.password), + "password": (formDataObject.password).toString(), [key]: formDataObject.totp, } } -- GitLab From 1f69ae64a3e850985360ad93ef35fa66e53ed980 Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 26 Sep 2025 12:52:25 -0700 Subject: [PATCH 4/8] Keep bootbox up when passwords do not match --- .../static/assets/js/shared/userSettings.js | 71 ++++++++++++------- 1 file changed, 45 insertions(+), 26 deletions(-) diff --git a/app/frontend/static/assets/js/shared/userSettings.js b/app/frontend/static/assets/js/shared/userSettings.js index 4216a93c..220e5745 100644 --- a/app/frontend/static/assets/js/shared/userSettings.js +++ b/app/frontend/static/assets/js/shared/userSettings.js @@ -24,40 +24,59 @@ $(document).on("submit", ".bootbox form", function (e) { $(".edit_password").on("click", async function () { const token = getCookie("_xsrf"); let user_id = $(this).data('id'); - bootbox.confirm(`
\ + bootbox.dialog({ + message: ` +
- -
\ + +
- - \ + +
-
`, async function (result) { - if (result) { - let password = validateForm(); - if (!password) { - return; - } - let res = await fetch(`/api/v2/users/${user_id}`, { - method: 'PATCH', - headers: { - 'X-XSRFToken': token - }, - body: JSON.stringify({ "password": toString(password) }), - }); - let responseData = await res.json(); - if (responseData.status === "ok") { - console.log(responseData.data) - } else { + + `, + buttons: { + cancel: { + label: "Cancel", + className: "btn-secondary" + }, + confirm: { + label: "OK", + className: "btn-primary", + callback: function () { + let password = validateForm(); + if (!password) { + return false; + } - bootbox.alert({ - title: responseData.status, - message: responseData.error_data - }); + (async () => { + password = password.toString(); + let res = await fetch(`/api/v2/users/${user_id}`, { + method: 'PATCH', + headers: { 'X-XSRFToken': token }, + body: JSON.stringify({ "password": password }), + }); + let responseData = await res.json(); + + if (responseData.status === "ok") { + console.log(responseData.data); + bootbox.hideAll(); + } else { + bootbox.alert({ + title: responseData.status, + message: responseData.error_data + }); + } + })(); + + return false; + } } } }); + }); $(".edit_user").on("click", function () { -- GitLab From 82cbe9d92c843cf869d07e99f96279984f637ae8 Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 26 Sep 2025 12:54:49 -0700 Subject: [PATCH 5/8] Close password dialogue on json validation failure --- app/frontend/static/assets/js/shared/userSettings.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/frontend/static/assets/js/shared/userSettings.js b/app/frontend/static/assets/js/shared/userSettings.js index 220e5745..b384b43a 100644 --- a/app/frontend/static/assets/js/shared/userSettings.js +++ b/app/frontend/static/assets/js/shared/userSettings.js @@ -64,6 +64,7 @@ $(".edit_password").on("click", async function () { console.log(responseData.data); bootbox.hideAll(); } else { + bootbox.hideAll(); bootbox.alert({ title: responseData.status, message: responseData.error_data -- GitLab From 085ad72a90756a63e3ef4eaa3c25d7d446803367 Mon Sep 17 00:00:00 2001 From: Zedifus Date: Mon, 6 Oct 2025 23:27:02 +0100 Subject: [PATCH 6/8] Update changelog !901 --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 408b28ca..6df05ecf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,12 @@ TBD ### Bug fixes - Resolve additional json being appended to downloaded files ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/902)) +- Fix certain users not showing up following a change made in `4.5.0` ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/901)) +- Fix password dialogue closing with no indicator the password did not change when the passwords did not match ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/901)) ### Tweaks -TBD +- Remove triple option for validation and use sole robust error ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/901)) +- Allow numeric passwords ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/901)) +- Enable use of `` key for password form submission ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/901)) ### Lang TBD

-- GitLab From f3555c0181bddf27ba0c4201c9f77f7eef666f77 Mon Sep 17 00:00:00 2001 From: = Date: Wed, 8 Oct 2025 17:09:48 -0400 Subject: [PATCH 7/8] Remove extraneous false --- app/frontend/static/assets/js/shared/userSettings.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/frontend/static/assets/js/shared/userSettings.js b/app/frontend/static/assets/js/shared/userSettings.js index b384b43a..f4f892cc 100644 --- a/app/frontend/static/assets/js/shared/userSettings.js +++ b/app/frontend/static/assets/js/shared/userSettings.js @@ -71,8 +71,6 @@ $(".edit_password").on("click", async function () { }); } })(); - - return false; } } } -- GitLab From 4d3d354640b6eb4b97a0be0c03b44bb626d260dc Mon Sep 17 00:00:00 2001 From: Zedifus Date: Mon, 13 Oct 2025 19:33:18 +0100 Subject: [PATCH 8/8] Update changelog !901 --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e06f59b6..3186bebe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,8 @@ TBD - Add extended debug logging to help troubleshoot MFA issues ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/898)) - Change upload progress bar to monitor chunk processing ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/896)) ### Lang -TBD +Consolidate "passLength" & "numbericPassword" to single "passProp" translation for validators ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/901)) +

## --- [4.5.4] - 2025/09/15 -- GitLab