Create invalid_char validators and apply to models
authorJ Guthrie <jamie.guthrie@gmail.com>
Sun, 4 Nov 2018 18:28:27 +0000 (18:28 +0000)
committerJ Guthrie <jamie.guthrie@gmail.com>
Mon, 5 Nov 2018 14:27:03 +0000 (14:27 +0000)
25 files changed:
app/models/changeset_comment.rb
app/models/changeset_tag.rb
app/models/diary_comment.rb
app/models/diary_entry.rb
app/models/issue_comment.rb
app/models/message.rb
app/models/node_tag.rb
app/models/note_comment.rb
app/models/old_node_tag.rb
app/models/old_relation_tag.rb
app/models/old_way_tag.rb
app/models/redaction.rb
app/models/relation_tag.rb
app/models/report.rb
app/models/trace.rb
app/models/tracetag.rb
app/models/user.rb
app/models/user_block.rb
app/models/user_preference.rb
app/models/way_tag.rb
app/validators/invalid_chars_validator.rb [new file with mode: 0644]
app/validators/invalid_url_chars_validator.rb [new file with mode: 0644]
app/validators/leading_whitespace_validator.rb [new file with mode: 0644]
app/validators/trailing_whitespace_validator.rb [new file with mode: 0644]
config/locales/en.yml

index 756fda1..232785d 100644 (file)
@@ -3,8 +3,8 @@
 # Table name: changeset_comments
 #
 #  id           :integer          not null, primary key
-#  changeset_id :integer          not null
-#  author_id    :integer          not null
+#  changeset_id :bigint(8)        not null
+#  author_id    :bigint(8)        not null
 #  body         :text             not null
 #  created_at   :datetime         not null
 #  visible      :boolean          not null
@@ -28,7 +28,7 @@ class ChangesetComment < ActiveRecord::Base
   validates :changeset, :presence => true, :associated => true
   validates :author, :presence => true, :associated => true
   validates :visible, :inclusion => [true, false]
-  validates :body, :format => /\A[^\x00-\x08\x0b-\x0c\x0e-\x1f\x7f\ufffe\uffff]*\z/
+  validates :body, :invalid_chars => true
 
   # Return the comment text
   def body
index 8d6cd45..1231fc2 100644 (file)
@@ -2,7 +2,7 @@
 #
 # Table name: changeset_tags
 #
-#  changeset_id :integer          not null, primary key
+#  changeset_id :bigint(8)        not null, primary key
 #  k            :string           default(""), not null, primary key
 #  v            :string           default(""), not null
 #
@@ -21,6 +21,6 @@ class ChangesetTag < ActiveRecord::Base
   belongs_to :changeset
 
   validates :changeset, :presence => true, :associated => true
-  validates :k, :v, :allow_blank => true, :length => { :maximum => 255 }
+  validates :k, :v, :allow_blank => true, :length => { :maximum => 255 }, :invalid_chars => true
   validates :k, :uniqueness => { :scope => :changeset_id }
 end
index 63eae3f..472129b 100644 (file)
@@ -2,9 +2,9 @@
 #
 # Table name: diary_comments
 #
-#  id             :integer          not null, primary key
-#  diary_entry_id :integer          not null
-#  user_id        :integer          not null
+#  id             :bigint(8)        not null, primary key
+#  diary_entry_id :bigint(8)        not null
+#  user_id        :bigint(8)        not null
 #  body           :text             not null
 #  created_at     :datetime         not null
 #  updated_at     :datetime         not null
@@ -28,7 +28,7 @@ class DiaryComment < ActiveRecord::Base
 
   scope :visible, -> { where(:visible => true) }
 
-  validates :body, :presence => true
+  validates :body, :presence => true, :invalid_chars => true
   validates :diary_entry, :user, :associated => true
 
   after_save :spam_check
index 2a24d80..d4139f6 100644 (file)
@@ -2,8 +2,8 @@
 #
 # Table name: diary_entries
 #
-#  id            :integer          not null, primary key
-#  user_id       :integer          not null
+#  id            :bigint(8)        not null, primary key
+#  user_id       :bigint(8)        not null
 #  title         :string           not null
 #  body          :text             not null
 #  created_at    :datetime         not null
@@ -37,7 +37,7 @@ class DiaryEntry < ActiveRecord::Base
 
   scope :visible, -> { where(:visible => true) }
 
-  validates :title, :body, :presence => true
+  validates :title, :body, :presence => true, :invalid_chars => true
   validates :title, :length => 1..255
   validates :latitude, :allow_nil => true,
                        :numericality => { :greater_than_or_equal_to => -90,
index 3a5894c..2fe96f4 100644 (file)
@@ -24,7 +24,7 @@ class IssueComment < ActiveRecord::Base
   belongs_to :issue
   belongs_to :user
 
-  validates :body, :presence => true
+  validates :body, :presence => true, :invalid_chars => true
   validates :user, :presence => true
   validates :issue, :presence => true
 end
index aff628e..2447c3b 100644 (file)
@@ -2,13 +2,13 @@
 #
 # Table name: messages
 #
-#  id                :integer          not null, primary key
-#  from_user_id      :integer          not null
+#  id                :bigint(8)        not null, primary key
+#  from_user_id      :bigint(8)        not null
 #  title             :string           not null
 #  body              :text             not null
 #  sent_on           :datetime         not null
 #  message_read      :boolean          default(FALSE), not null
-#  to_user_id        :integer          not null
+#  to_user_id        :bigint(8)        not null
 #  to_user_visible   :boolean          default(TRUE), not null
 #  from_user_visible :boolean          default(TRUE), not null
 #  body_format       :enum             default("markdown"), not null
@@ -32,6 +32,7 @@ class Message < ActiveRecord::Base
 
   validates :title, :presence => true, :utf8 => true, :length => 1..255
   validates :body, :sent_on, :sender, :recipient, :presence => true
+  validates :title, :body, :invalid_chars => true
 
   def self.from_mail(mail, from, to)
     if mail.multipart?
index 20065b9..d1e8005 100644 (file)
@@ -2,7 +2,7 @@
 #
 # Table name: current_node_tags
 #
-#  node_id :integer          not null, primary key
+#  node_id :bigint(8)        not null, primary key
 #  k       :string           default(""), not null, primary key
 #  v       :string           default(""), not null
 #
@@ -18,6 +18,6 @@ class NodeTag < ActiveRecord::Base
   belongs_to :node
 
   validates :node, :presence => true, :associated => true
-  validates :k, :v, :allow_blank => true, :length => { :maximum => 255 }
+  validates :k, :v, :allow_blank => true, :length => { :maximum => 255 }, :invalid_chars => true
   validates :k, :uniqueness => { :scope => :node_id }
 end
index 1772b3f..69a93c5 100644 (file)
@@ -34,7 +34,7 @@ class NoteComment < ActiveRecord::Base
   validates :author, :associated => true
   validates :event, :inclusion => %w[opened closed reopened commented hidden]
   validates :body, :length => { :maximum => 2000 },
-                   :format => /\A[^\x00-\x08\x0b-\x0c\x0e-\x1f\x7f\ufffe\uffff]*\z/
+                   :invalid_chars => true
 
   # Return the comment text
   def body
index 9e03d34..f6fb93e 100644 (file)
@@ -2,8 +2,8 @@
 #
 # Table name: node_tags
 #
-#  node_id :integer          not null, primary key
-#  version :integer          not null, primary key
+#  node_id :bigint(8)        not null, primary key
+#  version :bigint(8)        not null, primary key
 #  k       :string           default(""), not null, primary key
 #  v       :string           default(""), not null
 #
@@ -19,6 +19,6 @@ class OldNodeTag < ActiveRecord::Base
   belongs_to :old_node, :foreign_key => [:node_id, :version]
 
   validates :old_node, :presence => true, :associated => true
-  validates :k, :v, :allow_blank => true, :length => { :maximum => 255 }
+  validates :k, :v, :allow_blank => true, :length => { :maximum => 255 }, :invalid_chars => true
   validates :k, :uniqueness => { :scope => [:node_id, :version] }
 end
index 052b608..3b75e1c 100644 (file)
@@ -2,10 +2,10 @@
 #
 # Table name: relation_tags
 #
-#  relation_id :integer          default(0), not null, primary key
+#  relation_id :bigint(8)        default(0), not null, primary key
 #  k           :string           default(""), not null, primary key
 #  v           :string           default(""), not null
-#  version     :integer          not null, primary key
+#  version     :bigint(8)        not null, primary key
 #
 # Foreign Keys
 #
@@ -19,6 +19,6 @@ class OldRelationTag < ActiveRecord::Base
   belongs_to :old_relation, :foreign_key => [:relation_id, :version]
 
   validates :old_relation, :presence => true, :associated => true
-  validates :k, :v, :allow_blank => true, :length => { :maximum => 255 }
+  validates :k, :v, :allow_blank => true, :length => { :maximum => 255 }, :invalid_chars => true
   validates :k, :uniqueness => { :scope => [:relation_id, :version] }
 end
index 8fffebc..1404354 100644 (file)
@@ -2,10 +2,10 @@
 #
 # Table name: way_tags
 #
-#  way_id  :integer          default(0), not null, primary key
+#  way_id  :bigint(8)        default(0), not null, primary key
 #  k       :string           not null, primary key
 #  v       :string           not null
-#  version :integer          not null, primary key
+#  version :bigint(8)        not null, primary key
 #
 # Foreign Keys
 #
@@ -19,6 +19,6 @@ class OldWayTag < ActiveRecord::Base
   belongs_to :old_way, :foreign_key => [:way_id, :version]
 
   validates :old_way, :presence => true, :associated => true
-  validates :k, :v, :allow_blank => true, :length => { :maximum => 255 }
+  validates :k, :v, :allow_blank => true, :length => { :maximum => 255 }, :invalid_chars => true
   validates :k, :uniqueness => { :scope => [:way_id, :version] }
 end
index b835864..d9a5c6c 100644 (file)
@@ -7,7 +7,7 @@
 #  description        :text
 #  created_at         :datetime
 #  updated_at         :datetime
-#  user_id            :integer          not null
+#  user_id            :bigint(8)        not null
 #  description_format :enum             default("markdown"), not null
 #
 # Foreign Keys
@@ -31,6 +31,7 @@ class Redaction < ActiveRecord::Base
   has_many :old_ways
   has_many :old_relations
 
+  validates :title, :description, :invalid_chars => true
   validates :description, :presence => true
   validates :description_format, :inclusion => { :in => %w[text html markdown] }
 
index 5dc6099..02d5a21 100644 (file)
@@ -2,7 +2,7 @@
 #
 # Table name: current_relation_tags
 #
-#  relation_id :integer          not null, primary key
+#  relation_id :bigint(8)        not null, primary key
 #  k           :string           default(""), not null, primary key
 #  v           :string           default(""), not null
 #
@@ -18,6 +18,6 @@ class RelationTag < ActiveRecord::Base
   belongs_to :relation
 
   validates :relation, :presence => true, :associated => true
-  validates :k, :v, :allow_blank => true, :length => { :maximum => 255 }
+  validates :k, :v, :allow_blank => true, :length => { :maximum => 255 }, :invalid_chars => true
   validates :k, :uniqueness => { :scope => :relation_id }
 end
index 63296a0..ac00f1c 100644 (file)
@@ -27,7 +27,7 @@ class Report < ActiveRecord::Base
 
   validates :issue, :presence => true
   validates :user, :presence => true
-  validates :details, :presence => true
+  validates :details, :presence => true, :invalid_chars => true
   validates :category, :presence => true
 
   def self.categories_for(reportable)
index 5096a81..0e81805 100644 (file)
@@ -2,17 +2,18 @@
 #
 # Table name: gpx_files
 #
-#  id          :integer          not null, primary key
-#  user_id     :integer          not null
+#  id          :bigint(8)        not null, primary key
+#  user_id     :bigint(8)        not null
 #  visible     :boolean          default(TRUE), not null
 #  name        :string           default(""), not null
-#  size        :integer
+#  size        :bigint(8)
 #  latitude    :float
 #  longitude   :float
 #  timestamp   :datetime         not null
 #  description :string           default(""), not null
 #  inserted    :boolean          not null
 #  visibility  :enum             default("public"), not null
+#  length      :bigint(8)
 #
 # Indexes
 #
@@ -39,6 +40,7 @@ class Trace < ActiveRecord::Base
 
   validates :user, :presence => true, :associated => true
   validates :name, :presence => true, :length => 1..255
+  validates :name, :description, :invalid_chars => true
   validates :description, :presence => { :on => :create }, :length => 1..255
   validates :timestamp, :presence => true
   validates :visibility, :inclusion => %w[private public trackable identifiable]
index 1a4fbd3..cb7cf11 100644 (file)
@@ -2,9 +2,9 @@
 #
 # Table name: gpx_file_tags
 #
-#  gpx_id :integer          default(0), not null
+#  gpx_id :bigint(8)        default(0), not null
 #  tag    :string           not null
-#  id     :integer          not null, primary key
+#  id     :bigint(8)        not null, primary key
 #
 # Indexes
 #
@@ -22,5 +22,5 @@ class Tracetag < ActiveRecord::Base
   belongs_to :trace, :foreign_key => "gpx_id"
 
   validates :trace, :associated => true
-  validates :tag, :length => 1..255, :format => %r{\A[^/;.,?]*\z}
+  validates :tag, :length => 1..255, :format => %r{\A[^/;.,?]*\z}, :invalid_chars => true
 end
index 37351c6..0b0d373 100644 (file)
@@ -88,23 +88,16 @@ class User < ActiveRecord::Base
                     :default_url => "/assets/:class/:attachment/:style.png",
                     :styles => { :large => "100x100>", :small => "50x50>" }
 
-  INVALID_ASCII_CHARS = "/;.,?%#".freeze
-  INVALID_NON_ASCII_CHARS = "\x00-\x08\x0b-\x0c\x0e-\x1f\x7f\ufffe\uffff".freeze
-
   validates :display_name, :presence => true, :allow_nil => true, :length => 3..255,
                            :exclusion => %w[new terms save confirm confirm-email go_public reset-password forgot-password suspended]
   validates :display_name, :if => proc { |u| u.display_name_changed? },
                            :uniqueness => { :case_sensitive => false }
   validates :display_name, :if => proc { |u| u.display_name_changed? },
-                           :format => { :with => /\A[^#{INVALID_NON_ASCII_CHARS}]*\z/ }
-  validates :display_name, :if => proc { |u| u.display_name_changed? },
-                           :format => { :with => /\A[^#{INVALID_ASCII_CHARS}]*\z/,
-                                        :message => I18n.t("users.account.invalid chars", :invalid_chars => INVALID_ASCII_CHARS) }
-  validates :display_name, :if => proc { |u| u.display_name_changed? },
-                           :format => { :with => /\A\S/, :message => I18n.t("users.account.leading whitespace") }
-  validates :display_name, :if => proc { |u| u.display_name_changed? },
-                           :format => { :with => /\S\z/, :message => I18n.t("users.account.trailing whitespace") }
-  validates :email, :presence => true, :confirmation => true
+                           :invalid_chars => true,
+                           :invalid_url_chars => true,
+                           :leading_whitespace => true,
+                           :trailing_whitespace => true
+  validates :email, :presence => true, :confirmation => true, :invalid_chars => true
   validates :email, :if => proc { |u| u.email_changed? },
                     :uniqueness => { :case_sensitive => false }
   validates :pass_crypt, :confirmation => true, :length => 8..255
index 9f32862..f56f87b 100644 (file)
@@ -3,12 +3,12 @@
 # Table name: user_blocks
 #
 #  id            :integer          not null, primary key
-#  user_id       :integer          not null
-#  creator_id    :integer          not null
+#  user_id       :bigint(8)        not null
+#  creator_id    :bigint(8)        not null
 #  reason        :text             not null
 #  ends_at       :datetime         not null
 #  needs_view    :boolean          default(FALSE), not null
-#  revoker_id    :integer
+#  revoker_id    :bigint(8)
 #  created_at    :datetime
 #  updated_at    :datetime
 #  reason_format :enum             default("markdown"), not null
@@ -26,6 +26,7 @@
 
 class UserBlock < ActiveRecord::Base
   validate :moderator_permissions
+  validates :reason, :invalid_chars => true
 
   belongs_to :user, :class_name => "User", :foreign_key => :user_id
   belongs_to :creator, :class_name => "User", :foreign_key => :creator_id
index 69b0e9d..781dd62 100644 (file)
@@ -2,7 +2,7 @@
 #
 # Table name: user_preferences
 #
-#  user_id :integer          not null, primary key
+#  user_id :bigint(8)        not null, primary key
 #  k       :string           not null, primary key
 #  v       :string           not null
 #
@@ -17,7 +17,7 @@ class UserPreference < ActiveRecord::Base
   belongs_to :user
 
   validates :user, :presence => true, :associated => true
-  validates :k, :v, :length => 1..255
+  validates :k, :v, :length => 1..255, :invalid_chars => true
 
   # Turn this Node in to an XML Node without the <osm> wrapper.
   def to_xml_node
index 8ef75f3..4e0f7ee 100644 (file)
@@ -2,7 +2,7 @@
 #
 # Table name: current_way_tags
 #
-#  way_id :integer          not null, primary key
+#  way_id :bigint(8)        not null, primary key
 #  k      :string           default(""), not null, primary key
 #  v      :string           default(""), not null
 #
@@ -18,6 +18,6 @@ class WayTag < ActiveRecord::Base
   belongs_to :way
 
   validates :way, :presence => true, :associated => true
-  validates :k, :v, :allow_blank => true, :length => { :maximum => 255 }
+  validates :k, :v, :allow_blank => true, :length => { :maximum => 255 }, :invalid_chars => true
   validates :k, :uniqueness => { :scope => :way_id }
 end
diff --git a/app/validators/invalid_chars_validator.rb b/app/validators/invalid_chars_validator.rb
new file mode 100644 (file)
index 0000000..c324fd3
--- /dev/null
@@ -0,0 +1,9 @@
+class InvalidCharsValidator < ActiveModel::EachValidator
+  INVALID_CHARS = "\x00-\x08\x0b-\x0c\x0e-\x1f\x7f\ufffe\uffff".freeze
+
+  def validate_each(record, attribute, value)
+    if value =~ /[#{INVALID_CHARS}]/
+      record.errors[attribute] << (options[:message] || "contains invalid chars")
+    end
+  end
+end
\ No newline at end of file
diff --git a/app/validators/invalid_url_chars_validator.rb b/app/validators/invalid_url_chars_validator.rb
new file mode 100644 (file)
index 0000000..77a2fc5
--- /dev/null
@@ -0,0 +1,9 @@
+class InvalidUrlCharsValidator < ActiveModel::EachValidator
+  INVALID_URL_CHARS = "/;.,?%#".freeze
+
+  def validate_each(record, attribute, value)
+    if value =~ /[#{INVALID_URL_CHARS}]/
+      record.errors[attribute] << (options[:message] || I18n.t("validations.invalid chars", :invalid_chars => INVALID_URL_CHARS))
+    end
+  end
+end
\ No newline at end of file
diff --git a/app/validators/leading_whitespace_validator.rb b/app/validators/leading_whitespace_validator.rb
new file mode 100644 (file)
index 0000000..fcefb0a
--- /dev/null
@@ -0,0 +1,7 @@
+class LeadingWhitespaceValidator < ActiveModel::EachValidator
+  def validate_each(record, attribute, value)
+    if value =~ /\A\s/
+      record.errors[attribute] << (options[:message] || I18n.t("validations.leading whitespace"))
+    end
+  end
+end
\ No newline at end of file
diff --git a/app/validators/trailing_whitespace_validator.rb b/app/validators/trailing_whitespace_validator.rb
new file mode 100644 (file)
index 0000000..bb34ef4
--- /dev/null
@@ -0,0 +1,7 @@
+class TrailingWhitespaceValidator < ActiveModel::EachValidator
+  def validate_each(record, attribute, value)
+    if value =~ /\s\z/
+      record.errors[attribute] << (options[:message] || I18n.t("validations.trailing whitespace"))
+    end
+  end
+end
\ No newline at end of file
index 0a5ee72..c53ae19 100644 (file)
@@ -2134,9 +2134,6 @@ en:
       return to profile: Return to profile
       flash update success confirm needed: "User information updated successfully. Check your email for a note to confirm your new email address."
       flash update success: "User information updated successfully."
-      leading whitespace: "has leading whitespace"
-      trailing whitespace: "has trailing whitespace"
-      invalid chars: "cannot contain invalid chars: %{invalid_chars}"
     confirm:
       heading: Check your email!
       introduction_1: |
@@ -2565,3 +2562,7 @@ en:
       not_empty: "Redaction is not empty. Please un-redact all versions belonging to this redaction before destroying it."
       flash: "Redaction destroyed."
       error: "There was an error destroying this redaction."
+  validations:
+    leading whitespace: "has leading whitespace"
+    trailing whitespace: "has trailing whitespace"
+    invalid chars: "must not contain an invalid char: %{invalid_chars}"