mirror of
https://github.com/discourse/discourse.git
synced 2024-11-25 02:11:08 -06:00
DEV: Limit and validate category settings inputs (#20135)
We recently had a bug which caused auto-bumping to "not work". The problem was that the value had been set to 0.5, which when coerced to an integer turned into 0. So the feature is "working as intended", but there's a possibility of misconfiguration. When looking into this, I noticed that the inputs on the category settings page doesn't have any particular sanitisation in the front-end, and also one or two validations missing in the back-end. This change: - Takes an existing component, NumberField and enhances that by only allowing numeric input, essentially turning it into a managed input using the same approach as our PasswordField. - Changes the numeric inputs on category settings page to use this component. - Adds appropriate min constraints to the fields to disallow out-of-range values. - Adds missing back-end validations to relevant fields.
This commit is contained in:
parent
25f2fb61b8
commit
676d5fadab
@ -2,9 +2,37 @@ import I18n from "I18n";
|
||||
import TextField from "discourse/components/text-field";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
|
||||
const ALLOWED_KEYS = [
|
||||
"Enter",
|
||||
"Backspace",
|
||||
"Tab",
|
||||
"Delete",
|
||||
"ArrowLeft",
|
||||
"ArrowUp",
|
||||
"ArrowRight",
|
||||
"ArrowDown",
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"7",
|
||||
"8",
|
||||
"9",
|
||||
];
|
||||
|
||||
export default TextField.extend({
|
||||
classNameBindings: ["invalid"],
|
||||
|
||||
keyDown: function (e) {
|
||||
return (
|
||||
ALLOWED_KEYS.includes(e.key) ||
|
||||
(e.key === "-" && parseInt(this.get("min"), 10) < 0)
|
||||
);
|
||||
},
|
||||
|
||||
@discourseComputed("number")
|
||||
value: {
|
||||
get(number) {
|
||||
|
@ -4,11 +4,12 @@
|
||||
<label for="category-position">
|
||||
{{i18n "category.position"}}
|
||||
</label>
|
||||
<TextField
|
||||
@value={{this.category.position}}
|
||||
<NumberField
|
||||
@number={{this.category.position}}
|
||||
@id="category-position"
|
||||
@class="position-input"
|
||||
@type="number"
|
||||
@min="0"
|
||||
/>
|
||||
</section>
|
||||
{{/if}}
|
||||
@ -34,10 +35,11 @@
|
||||
{{i18n "category.num_featured_topics"}}
|
||||
{{/if}}
|
||||
</label>
|
||||
<TextField
|
||||
@value={{this.category.num_featured_topics}}
|
||||
<NumberField
|
||||
@number={{this.category.num_featured_topics}}
|
||||
@id="category-number-featured-topics"
|
||||
@type="number"
|
||||
@min="1"
|
||||
/>
|
||||
</section>
|
||||
|
||||
@ -185,10 +187,11 @@
|
||||
<label for="category-number-daily-bump">
|
||||
{{i18n "category.num_auto_bump_daily"}}
|
||||
</label>
|
||||
<TextField
|
||||
@value={{this.category.custom_fields.num_auto_bump_daily}}
|
||||
<NumberField
|
||||
@number={{this.category.custom_fields.num_auto_bump_daily}}
|
||||
@id="category-number-daily-bump"
|
||||
@type="number"
|
||||
@min="0"
|
||||
/>
|
||||
</section>
|
||||
</section>
|
||||
|
@ -21,6 +21,7 @@
|
||||
<NumberField
|
||||
@number={{readonly cat.position}}
|
||||
@change={{action "change" cat}}
|
||||
@min="0"
|
||||
/>
|
||||
<DButton
|
||||
@class="btn-default no-text"
|
||||
|
@ -73,6 +73,12 @@ class Category < ActiveRecord::Base
|
||||
validate :ensure_slug
|
||||
validate :permissions_compatibility_validator
|
||||
|
||||
validates :default_slow_mode_seconds,
|
||||
numericality: {
|
||||
only_integer: true,
|
||||
greater_than: 0,
|
||||
},
|
||||
allow_nil: true
|
||||
validates :auto_close_hours,
|
||||
numericality: {
|
||||
greater_than: 0,
|
||||
|
@ -7,6 +7,12 @@ RSpec.describe Category do
|
||||
it { is_expected.to validate_presence_of :user_id }
|
||||
it { is_expected.to validate_presence_of :name }
|
||||
|
||||
it do
|
||||
is_expected.to validate_numericality_of(:default_slow_mode_seconds).is_greater_than(
|
||||
0,
|
||||
).only_integer
|
||||
end
|
||||
|
||||
it "validates uniqueness of name" do
|
||||
Fabricate(:category_with_definition)
|
||||
is_expected.to validate_uniqueness_of(:name).scoped_to(:parent_category_id).case_insensitive
|
||||
|
Loading…
Reference in New Issue
Block a user