X-Git-Url: https://git.openstreetmap.org/rails.git/blobdiff_plain/c819c8114d6e88f7e3a7ec4da93b4060e7aff3bc..64816e50b57ced52f5fb0082f97b2844e002cf11:/app/models/user.rb diff --git a/app/models/user.rb b/app/models/user.rb index 1cd8c6d89..37351c6b2 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -33,6 +33,7 @@ # image_use_gravatar :boolean default(FALSE), not null # image_content_type :string # auth_provider :string +# home_tile :integer # # Indexes # @@ -41,6 +42,7 @@ # users_display_name_lower_idx (lower((display_name)::text)) # users_email_idx (email) UNIQUE # users_email_lower_idx (lower((email)::text)) +# users_home_idx (home_tile) # class User < ActiveRecord::Base @@ -73,6 +75,11 @@ class User < ActiveRecord::Base has_many :roles, :class_name => "UserRole" + has_many :issues, :class_name => "Issue", :foreign_key => :reported_user_id + has_many :issue_comments + + has_many :reports + scope :visible, -> { where(:status => %w[pending active confirmed]) } scope :active, -> { where(:status => %w[active confirmed]) } scope :identifiable, -> { where(:data_public => true) } @@ -81,21 +88,28 @@ 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 => %r{\A[^\x00-\x1f\x7f\ufffe\uffff/;.,?%#]*\z} } + :format => { :with => /\A[^#{INVALID_NON_ASCII_CHARS}]*\z/ } validates :display_name, :if => proc { |u| u.display_name_changed? }, - :format => { :with => /\A\S/, :message => "has leading whitespace" } + :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 => /\S\z/, :message => "has trailing whitespace" } + :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 validates :email, :if => proc { |u| u.email_changed? }, :uniqueness => { :case_sensitive => false } validates :pass_crypt, :confirmation => true, :length => 8..255 - validates :home_lat, :home_lon, :allow_nil => true, :numericality => true + validates :home_lat, :allow_nil => true, :numericality => true, :inclusion => { :in => -90..90 } + validates :home_lon, :allow_nil => true, :numericality => true, :inclusion => { :in => -180..180 } validates :home_zoom, :allow_nil => true, :numericality => { :only_integer => true } validates :preferred_editor, :inclusion => Editors::ALL_EDITORS, :allow_nil => true validates :image, :attachment_content_type => { :content_type => %r{\Aimage/.*\Z} } @@ -107,7 +121,13 @@ class User < ActiveRecord::Base after_initialize :set_defaults before_save :encrypt_password + before_save :update_tile after_save :spam_check + after_save :reset_preferred_languages + + def to_param + display_name + end def self.authenticate(options) if options[:username] && options[:password] @@ -181,14 +201,24 @@ class User < ActiveRecord::Base end def preferred_languages - @locales ||= Locale.list(languages) + @preferred_languages ||= Locale.list(languages) + end + + def reset_preferred_languages + @preferred_languages = nil end def nearby(radius = NEARBY_RADIUS, num = NEARBY_USERS) if home_lon && home_lat gc = OSM::GreatCircle.new(home_lat, home_lon) + sql_for_area = QuadTile.sql_for_area(gc.bounds(radius), "home_") sql_for_distance = gc.sql_for_distance("home_lat", "home_lon") - nearby = User.where("id != ? AND status IN (\'active\', \'confirmed\') AND data_public = ? AND #{sql_for_distance} <= ?", id, true, radius).order(sql_for_distance).limit(num) + nearby = User.active.identifiable + .where("id != ?", id) + .where(sql_for_area) + .where("#{sql_for_distance} <= ?", radius) + .order(Arel.sql(sql_for_distance)) + .limit(num) else nearby = [] end @@ -298,4 +328,8 @@ class User < ActiveRecord::Base self.pass_crypt_confirmation = nil end end + + def update_tile + self.home_tile = QuadTile.tile_for_point(home_lat, home_lon) if home_lat && home_lon + end end