Merge branch 'master' into openstreetbugs

Conflicts:
	app/views/browse/_map.html.erb
	app/views/site/index.html.erb
	config/initializers/mime_types.rb
	config/routes.rb
	lib/map_boundary.rb
	lib/migrate.rb
	lib/osm.rb
	vendor/assets/openlayers/OpenLayers.js
This commit is contained in:
Tom Hughes 2012-01-05 20:15:53 +00:00
commit 52e5fa6ad7
888 changed files with 23910 additions and 22316 deletions

View file

@ -1,5 +1,11 @@
class AccessToken<OauthToken
validates_presence_of :user
class AccessToken < OauthToken
belongs_to :user
belongs_to :client_application
scope :valid, where(:invalidated_at => nil)
validates_presence_of :user, :secret
before_create :set_authorized_at
protected
@ -7,4 +13,4 @@ protected
def set_authorized_at
self.authorized_at = Time.now
end
end
end

View file

@ -1,15 +1,5 @@
class Acl < ActiveRecord::Base
def self.find_by_address(address, options)
self.with_scope(:find => {:conditions => ["#{inet_aton} & netmask = address", address]}) do
return self.find(:first, options)
end
end
def self.find_all_by_address(address, options)
self.with_scope(:find => {:conditions => ["#{inet_aton} & netmask = address", address]}) do
return self.find(:all, options)
end
end
scope :address, lambda { |address| where("#{inet_aton} & netmask = address", address) }
private

View file

@ -3,7 +3,7 @@ class Changeset < ActiveRecord::Base
belongs_to :user
has_many :changeset_tags, :foreign_key => 'id'
has_many :changeset_tags
has_many :nodes
has_many :ways
@ -20,6 +20,8 @@ class Changeset < ActiveRecord::Base
validates_numericality_of :user_id, :integer_only => true
validates_numericality_of :num_changes, :integer_only => true, :greater_than_or_equal_to => 0
before_save :update_closed_at
# over-expansion factor to use when updating the bounding box
EXPAND = 0.1
@ -52,7 +54,7 @@ class Changeset < ActiveRecord::Base
def self.from_xml(xml, create=false)
begin
p = XML::Parser.string(xml)
p = XML::Parser.string(xml, :options => XML::Parser::Options::NOERROR)
doc = p.parse
doc.find('//osm/changeset').each do |pt|
@ -88,21 +90,11 @@ class Changeset < ActiveRecord::Base
# returns the bounding box of the changeset. it is possible that some
# or all of the values will be nil, indicating that they are undefined.
def bbox
@bbox ||= [ min_lon, min_lat, max_lon, max_lat ]
@bbox ||= BoundingBox.new(min_lon, min_lat, max_lon, max_lat)
end
def has_valid_bbox?
not bbox.include? nil
end
##
# returns area of the changset bbox as a rough comparitive quantity for use of changset displays
def area
if has_valid_bbox?
(max_lon - min_lon) * (max_lat - min_lat)
else
0
end
bbox.complete?
end
##
@ -110,26 +102,12 @@ class Changeset < ActiveRecord::Base
# expand a little bit more in the direction of the expansion, so that
# further expansions may be unnecessary. this is an optimisation
# suggested on the wiki page by kleptog.
def update_bbox!(array)
# ensure that bbox is cached and has no nils in it. if there are any
# nils, just use the bounding box update to write over them.
@bbox = bbox.zip(array).collect { |a, b| a.nil? ? b : a }
# only try to update the bbox if there is a value for every coordinate
# which there will be from the previous line as long as both array and
# bbox are all non-nil.
if has_valid_bbox? and array.all?
# FIXME - this looks nasty and violates DRY... is there any prettier
# way to do this?
@bbox[0] = [-180 * GeoRecord::SCALE, array[0] + EXPAND * (@bbox[0] - @bbox[2])].max if array[0] < @bbox[0]
@bbox[1] = [ -90 * GeoRecord::SCALE, array[1] + EXPAND * (@bbox[1] - @bbox[3])].max if array[1] < @bbox[1]
@bbox[2] = [ 180 * GeoRecord::SCALE, array[2] + EXPAND * (@bbox[2] - @bbox[0])].min if array[2] > @bbox[2]
@bbox[3] = [ 90 * GeoRecord::SCALE, array[3] + EXPAND * (@bbox[3] - @bbox[1])].min if array[3] > @bbox[3]
def update_bbox!(bbox_update)
bbox.expand!(bbox_update, EXPAND)
# update active record. rails 2.1's dirty handling should take care of
# whether this object needs saving or not.
self.min_lon, self.min_lat, self.max_lon, self.max_lat = @bbox
end
# update active record. rails 2.1's dirty handling should take care of
# whether this object needs saving or not.
self.min_lon, self.min_lat, self.max_lon, self.max_lat = @bbox.to_a if bbox.complete?
end
##
@ -175,13 +153,13 @@ class Changeset < ActiveRecord::Base
self.save!
tags = self.tags
ChangesetTag.delete_all(['id = ?', self.id])
ChangesetTag.delete_all(:changeset_id => self.id)
tags.each do |k,v|
tag = ChangesetTag.new
tag.changeset_id = self.id
tag.k = k
tag.v = v
tag.id = self.id
tag.save!
end
end
@ -191,7 +169,7 @@ class Changeset < ActiveRecord::Base
# set the auto-close time to be one hour in the future unless
# that would make it more than 24h long, in which case clip to
# 24h, as this has been decided is a reasonable time limit.
def before_save
def update_closed_at
if self.is_open?
if (closed_at - created_at) > (MAX_TIME_OPEN - IDLE_TIMEOUT)
self.closed_at = created_at + MAX_TIME_OPEN
@ -235,10 +213,9 @@ class Changeset < ActiveRecord::Base
el1['closed_at'] = self.closed_at.xmlschema unless is_open?
el1['open'] = is_open?.to_s
el1['min_lon'] = (bbox[0].to_f / GeoRecord::SCALE).to_s unless bbox[0].nil?
el1['min_lat'] = (bbox[1].to_f / GeoRecord::SCALE).to_s unless bbox[1].nil?
el1['max_lon'] = (bbox[2].to_f / GeoRecord::SCALE).to_s unless bbox[2].nil?
el1['max_lat'] = (bbox[3].to_f / GeoRecord::SCALE).to_s unless bbox[3].nil?
if bbox.complete?
bbox.to_unscaled.add_bounds_to(el1, '_')
end
# NOTE: changesets don't include the XML of the changes within them,
# they are just structures for tagging. to get the osmChange of a

View file

@ -1,8 +1,10 @@
class ChangesetTag < ActiveRecord::Base
belongs_to :changeset, :foreign_key => 'id'
set_primary_keys :changeset_id, :k
validates_presence_of :id
validates_length_of :k, :v, :maximum => 255, :allow_blank => true
validates_uniqueness_of :id, :scope => :k
validates_numericality_of :id, :only_integer => true
belongs_to :changeset
validates_presence_of :changeset
validates_length_of :k, :maximum => 255, :allow_blank => true
validates_uniqueness_of :k, :scope => :changeset_id
validates_length_of :v, :maximum => 255, :allow_blank => true
end

View file

@ -1,16 +1,20 @@
require 'oauth'
class ClientApplication < ActiveRecord::Base
belongs_to :user
has_many :tokens, :class_name => "OauthToken"
has_many :access_tokens
has_many :oauth2_verifiers
has_many :oauth_tokens
validates_presence_of :name, :url, :key, :secret
validates_uniqueness_of :key
before_validation_on_create :generate_keys
validates_format_of :url, :with => /\Ahttp(s?):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/i
validates_format_of :support_url, :with => /\Ahttp(s?):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/i, :allow_blank=>true
validates_format_of :callback_url, :with => /\A[a-z][a-z0-9.+-]*:\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/i, :allow_blank=>true
before_validation :generate_keys, :on => :create
attr_accessor :token_callback_url
def self.find_token(token_key)
@ -25,15 +29,10 @@ class ClientApplication < ActiveRecord::Base
def self.verify_request(request, options = {}, &block)
begin
signature = OAuth::Signature.build(request, options, &block)
logger.info "Signature Base String: #{signature.signature_base_string}"
logger.info "Consumer: #{signature.send :consumer_key}"
logger.info "Token: #{signature.send :token}"
return false unless OauthNonce.remember(signature.request.nonce, signature.request.timestamp)
value = signature.verify
logger.info "Signature verification returned: #{value.to_s}"
value
rescue OAuth::Signature::UnknownSignatureMethod => e
logger.info "ERROR"+e.to_s
false
end
end
@ -50,12 +49,16 @@ class ClientApplication < ActiveRecord::Base
@oauth_client ||= OAuth::Consumer.new(key, secret)
end
def create_request_token
RequestToken.create :client_application => self, :callback_url => self.token_callback_url
def create_request_token(params={})
params = { :client_application => self, :callback_url => self.token_callback_url }
permissions.each do |p|
params[p] = true
end
RequestToken.create(params)
end
def access_token_for_user(user)
unless token = access_tokens.find(:first, :conditions => { :user_id => user.id, :invalidated_at => nil })
unless token = access_tokens.valid.where(:user_id => user).first
params = { :user => user }
permissions.each do |p|
@ -82,8 +85,7 @@ protected
:allow_write_api, :allow_read_gpx, :allow_write_gpx ]
def generate_keys
oauth_client = oauth_server.generate_consumer_credentials
self.key = oauth_client.key
self.secret = oauth_client.secret
self.key = OAuth::Helper.generate_key(40)[0,40]
self.secret = OAuth::Helper.generate_key(40)[0,40]
end
end

View file

@ -13,6 +13,8 @@ class DiaryEntry < ActiveRecord::Base
},
:order => "diary_comments.id"
scope :visible, where(:visible => true)
validates_presence_of :title, :body
validates_length_of :title, :within => 1..255
#validates_length_of :language, :within => 2..5, :allow_nil => false

View file

@ -17,8 +17,8 @@ private
def expire_cache_for(record)
case
when record.is_a?(DiaryEntry): entry = record
when record.is_a?(DiaryComment): entry = record.diary_entry
when record.is_a?(DiaryEntry) then entry = record
when record.is_a?(DiaryComment) then entry = record.diary_entry
end
expire_action(:controller => 'diary_entry', :action => 'view', :display_name => entry.user.display_name, :id => entry.id)

View file

@ -8,12 +8,12 @@ class Node < ActiveRecord::Base
belongs_to :changeset
has_many :old_nodes, :foreign_key => :id, :order => :version
has_many :old_nodes, :order => :version
has_many :way_nodes
has_many :ways, :through => :way_nodes
has_many :node_tags, :foreign_key => :id
has_many :node_tags
has_many :old_way_nodes
has_many :ways_via_history, :class_name=> "Way", :through => :old_way_nodes, :source => :way
@ -30,9 +30,12 @@ class Node < ActiveRecord::Base
validate :validate_position
validates_associated :changeset
scope :visible, where(:visible => true)
scope :invisible, where(:visible => false)
# Sanity check the latitude and longitude and add an error if it's broken
def validate_position
errors.add_to_base("Node is not in the world") unless in_world?
errors.add(:base, "Node is not in the world") unless in_world?
end
#
@ -41,7 +44,6 @@ class Node < ActiveRecord::Base
# Also adheres to limitations such as within max_number_of_nodes
#
def self.search(bounding_box, tags = {})
min_lon, min_lat, max_lon, max_lat = *bounding_box
# @fixme a bit of a hack to search for only visible nodes
# couldn't think of another to add to tags condition
#conditions_hash = tags.merge({ 'visible' => 1 })
@ -56,9 +58,8 @@ class Node < ActiveRecord::Base
#end
#conditions = keys.join(' AND ')
find_by_area(min_lat, min_lon, max_lat, max_lon,
:conditions => {:visible => true},
:limit => MAX_NUMBER_OF_NODES+1)
find_by_area(bounding_box, :conditions => {:visible => true},
:limit => MAX_NUMBER_OF_NODES+1)
end
# Read in xml as text and return it's Node object representation
@ -118,7 +119,7 @@ class Node < ActiveRecord::Base
# the bounding box around a node, which is used for determining the changeset's
# bounding box
def bbox
[ longitude, latitude, longitude, latitude ]
BoundingBox.new(longitude, latitude, longitude, latitude)
end
# Should probably be renamed delete_from to come in line with update
@ -133,13 +134,11 @@ class Node < ActiveRecord::Base
Node.transaction do
self.lock!
check_consistency(self, new_node, user)
way = WayNode.find(:first, :joins => :way,
:conditions => [ "current_ways.visible = ? AND current_way_nodes.node_id = ?", true, self.id ])
raise OSM::APIPreconditionFailedError.new("Node #{self.id} is still used by way #{way.way.id}.") unless way.nil?
ways = Way.joins(:way_nodes).where(:visible => true, :current_way_nodes => { :node_id => id }).order(:id)
raise OSM::APIPreconditionFailedError.new("Node #{self.id} is still used by ways #{ways.collect { |w| w.id }.join(",")}.") unless ways.empty?
rel = RelationMember.find(:first, :joins => :relation,
:conditions => [ "visible = ? AND member_type='Node' and member_id=? ", true, self.id])
raise OSM::APIPreconditionFailedError.new("Node #{self.id} is still used by relation #{rel.relation.id}.") unless rel.nil?
rels = Relation.joins(:relation_members).where(:visible => true, :current_relation_members => { :member_type => "Node", :member_id => id }).order(:id)
raise OSM::APIPreconditionFailedError.new("Node #{self.id} is still used by relations #{rels.collect { |r| r.id }.join(",")}.") unless rels.empty?
self.changeset_id = new_node.changeset_id
self.tags = {}
@ -288,12 +287,12 @@ class Node < ActiveRecord::Base
# Create a NodeTag
tags = self.tags
NodeTag.delete_all(['id = ?', self.id])
NodeTag.delete_all(:node_id => self.id)
tags.each do |k,v|
tag = NodeTag.new
tag.node_id = self.id
tag.k = k
tag.v = v
tag.id = self.id
tag.save!
end

View file

@ -1,10 +1,11 @@
class NodeTag < ActiveRecord::Base
set_table_name 'current_node_tags'
set_primary_keys :node_id, :k
belongs_to :node, :foreign_key => 'id'
belongs_to :node
validates_presence_of :id
validates_length_of :k, :v, :maximum => 255, :allow_blank => true
validates_uniqueness_of :id, :scope => :k
validates_numericality_of :id, :only_integer => true
validates_presence_of :node
validates_length_of :k, :maximum => 255, :allow_blank => true
validates_uniqueness_of :k, :scope => :node_id
validates_length_of :v, :maximum => 255, :allow_blank => true
end

View file

@ -1,98 +1,117 @@
class Notifier < ActionMailer::Base
default :from => EMAIL_FROM,
:return_path => EMAIL_RETURN_PATH,
:auto_submitted => "auto-generated"
helper :application
def signup_confirm(user, token)
common_headers user
subject I18n.t('notifier.signup_confirm.subject')
body :url => url_for(:host => SERVER_URL,
:controller => "user", :action => "confirm",
:display_name => user.display_name,
:confirm_string => token.token)
@locale = user.preferred_language_from(I18n.available_locales)
@url = url_for(:host => SERVER_URL,
:controller => "user", :action => "confirm",
:display_name => user.display_name,
:confirm_string => token.token)
mail :to => user.email,
:subject => I18n.t('notifier.signup_confirm.subject', :locale => @locale)
end
def email_confirm(user, token)
common_headers user
recipients user.new_email
subject I18n.t('notifier.email_confirm.subject')
body :address => user.new_email,
:url => url_for(:host => SERVER_URL,
:controller => "user", :action => "confirm_email",
:confirm_string => token.token)
@locale = user.preferred_language_from(I18n.available_locales)
@address = user.new_email
@url = url_for(:host => SERVER_URL,
:controller => "user", :action => "confirm_email",
:confirm_string => token.token)
mail :to => user.new_email,
:subject => I18n.t('notifier.email_confirm.subject', :locale => @locale)
end
def lost_password(user, token)
common_headers user
subject I18n.t('notifier.lost_password.subject')
body :url => url_for(:host => SERVER_URL,
:controller => "user", :action => "reset_password",
:token => token.token)
@locale = user.preferred_language_from(I18n.available_locales)
@url = url_for(:host => SERVER_URL,
:controller => "user", :action => "reset_password",
:token => token.token)
mail :to => user.email,
:subject => I18n.t('notifier.lost_password.subject', :locale => @locale)
end
def gpx_success(trace, possible_points)
common_headers trace.user
subject I18n.t('notifier.gpx_notification.success.subject')
body :trace_name => trace.name,
:trace_points => trace.size,
:trace_description => trace.description,
:trace_tags => trace.tags,
:possible_points => possible_points
@locale = trace.user.preferred_language_from(I18n.available_locales)
@trace_name = trace.name
@trace_points = trace.size
@trace_description = trace.description
@trace_tags = trace.tags
@possible_points = possible_points
mail :to => trace.user.email,
:subject => I18n.t('notifier.gpx_notification.success.subject', :locale => @locale)
end
def gpx_failure(trace, error)
common_headers trace.user
from "webmaster@openstreetmap.org"
subject I18n.t('notifier.gpx_notification.failure.subject')
body :trace_name => trace.name,
:trace_description => trace.description,
:trace_tags => trace.tags,
:error => error
@locale = trace.user.preferred_language_from(I18n.available_locales)
@trace_name = trace.name
@trace_description = trace.description
@trace_tags = trace.tags
@error = error
mail :to => trace.user.email,
:subject => I18n.t('notifier.gpx_notification.failure.subject', :locale => @locale)
end
def message_notification(message)
common_headers message.recipient
from_header message.sender.display_name, "m", message.id, message.digest
subject I18n.t('notifier.message_notification.subject_header', :subject => message.title, :locale => locale)
body :to_user => message.recipient.display_name,
:from_user => message.sender.display_name,
:body => message.body,
:title => message.title,
:readurl => url_for(:host => SERVER_URL,
:controller => "message", :action => "read",
:message_id => message.id),
:replyurl => url_for(:host => SERVER_URL,
:controller => "message", :action => "reply",
:message_id => message.id)
@locale = message.recipient.preferred_language_from(I18n.available_locales)
@to_user = message.recipient.display_name
@from_user = message.sender.display_name
@text = message.body
@title = message.title
@readurl = url_for(:host => SERVER_URL,
:controller => "message", :action => "read",
:message_id => message.id)
@replyurl = url_for(:host => SERVER_URL,
:controller => "message", :action => "reply",
:message_id => message.id)
mail :from => from_address(message.sender.display_name, "m", message.id, message.digest),
:to => message.recipient.email,
:subject => I18n.t('notifier.message_notification.subject_header', :subject => message.title, :locale => @locale)
end
def diary_comment_notification(comment)
common_headers comment.diary_entry.user
from_header comment.user.display_name, "c", comment.id, comment.digest
subject I18n.t('notifier.diary_comment_notification.subject', :user => comment.user.display_name, :locale => locale)
body :to_user => comment.diary_entry.user.display_name,
:from_user => comment.user.display_name,
:body => comment.body,
:title => comment.diary_entry.title,
:readurl => url_for(:host => SERVER_URL,
:controller => "diary_entry",
:action => "view",
:display_name => comment.diary_entry.user.display_name,
:id => comment.diary_entry.id,
:anchor => "comment#{comment.id}"),
:commenturl => url_for(:host => SERVER_URL,
:controller => "diary_entry",
:action => "view",
:display_name => comment.diary_entry.user.display_name,
:id => comment.diary_entry.id,
:anchor => "newcomment"),
:replyurl => url_for(:host => SERVER_URL,
:controller => "message",
:action => "new",
:display_name => comment.user.display_name,
:title => "Re: #{comment.diary_entry.title}")
@locale = comment.diary_entry.user.preferred_language_from(I18n.available_locales)
@to_user = comment.diary_entry.user.display_name
@from_user = comment.user.display_name
@text = comment.body
@title = comment.diary_entry.title
@readurl = url_for(:host => SERVER_URL,
:controller => "diary_entry",
:action => "view",
:display_name => comment.diary_entry.user.display_name,
:id => comment.diary_entry.id,
:anchor => "comment#{comment.id}")
@commenturl = url_for(:host => SERVER_URL,
:controller => "diary_entry",
:action => "view",
:display_name => comment.diary_entry.user.display_name,
:id => comment.diary_entry.id,
:anchor => "newcomment")
@replyurl = url_for(:host => SERVER_URL,
:controller => "message",
:action => "new",
:display_name => comment.user.display_name,
:title => "Re: #{comment.diary_entry.title}")
mail :from => from_address(comment.user.display_name, "c", comment.id, comment.digest),
:to => comment.diary_entry.user.email,
:subject => I18n.t('notifier.diary_comment_notification.subject', :user => comment.user.display_name, :locale => @locale)
end
def friend_notification(friend)
common_headers friend.befriendee
subject I18n.t('notifier.friend_notification.subject', :user => friend.befriender.display_name, :locale => locale)
body :friend => friend
@locale = friend.befriendee.preferred_language_from(I18n.available_locales)
@friend = friend
mail :to => friend.befriendee.email,
:subject => I18n.t('notifier.friend_notification.subject', :user => friend.befriender.display_name, :locale => @locale)
end
def note_comment_notification(comment, recipient)
@ -113,17 +132,11 @@ class Notifier < ActionMailer::Base
private
def common_headers(recipient)
recipients recipient.email
locale recipient.preferred_language_from(I18n.available_locales)
from EMAIL_FROM
headers "return-path" => EMAIL_RETURN_PATH,
"Auto-Submitted" => "auto-generated"
end
def from_header(name, type, id, digest)
if domain = MESSAGES_DOMAIN
from quote_address_if_necessary("#{name} <#{type}-#{id}-#{digest[0,6]}@#{domain}>", "utf-8")
def from_address(name, type, id, digest)
if Object.const_defined?(:MESSAGES_DOMAIN) and domain = MESSAGES_DOMAIN
"#{name} <#{type}-#{id}-#{digest[0,6]}@#{domain}>"
else
EMAIL_FROM
end
end
end

View file

@ -0,0 +1,21 @@
class Oauth2Token < AccessToken
attr_accessor :state
def as_json(options={})
d = {:access_token=>token, :token_type => 'bearer'}
d[:expires_in] = expires_in if expires_at
d
end
def to_query
q = "access_token=#{token}&token_type=bearer"
q << "&state=#{URI.escape(state)}" if @state
q << "&expires_in=#{expires_in}" if expires_at
q << "&scope=#{URI.escape(scope)}" if scope
q
end
def expires_in
expires_at.to_i - Time.now.to_i
end
end

View file

@ -0,0 +1,34 @@
class Oauth2Verifier < OauthToken
validates_presence_of :user
attr_accessor :state
def exchange!(params={})
OauthToken.transaction do
token = Oauth2Token.create! :user=>user,:client_application=>client_application, :scope => scope
invalidate!
token
end
end
def code
token
end
def redirect_url
callback_url
end
def to_query
q = "code=#{token}"
q << "&state=#{URI.escape(state)}" if @state
q
end
protected
def generate_keys
self.token = OAuth::Helper.generate_key(20)[0,20]
self.expires_at = 10.minutes.from_now
self.authorized_at = Time.now
end
end

View file

@ -1,19 +1,13 @@
class OauthToken < ActiveRecord::Base
belongs_to :client_application
belongs_to :user
scope :authorized, where("authorized_at IS NOT NULL and invalidated_at IS NULL")
validates_uniqueness_of :token
validates_presence_of :client_application, :token, :secret
before_validation_on_create :generate_keys
def self.find_token(token_key)
token = OauthToken.find_by_token(token_key, :include => :client_application)
if token && token.authorized?
logger.info "Loaded #{token.token} which was authorized by (user_id=#{token.user_id}) on the #{token.authorized_at}"
token
else
nil
end
end
validates_presence_of :client_application, :token
before_validation :generate_keys, :on => :create
def invalidated?
invalidated_at != nil
@ -34,8 +28,7 @@ class OauthToken < ActiveRecord::Base
protected
def generate_keys
@oauth_token = client_application.oauth_server.generate_credentials
self.token = @oauth_token[0]
self.secret = @oauth_token[1]
self.token = OAuth::Helper.generate_key(40)[0,40]
self.secret = OAuth::Helper.generate_key(40)[0,40]
end
end

View file

@ -3,11 +3,8 @@ class OldNode < ActiveRecord::Base
include ConsistencyValidations
set_table_name 'nodes'
# Should probably have the composite primary key set in the model
# however there are some weird bugs happening when you do
#set_primary_keys :id, :version
set_primary_keys :node_id, :version
validates_presence_of :changeset_id, :timestamp
validates_inclusion_of :visible, :in => [ true, false ]
validates_numericality_of :latitude, :longitude
@ -17,7 +14,7 @@ class OldNode < ActiveRecord::Base
belongs_to :changeset
def validate_position
errors.add_to_base("Node is not in the world") unless in_world?
errors.add(:base, "Node is not in the world") unless in_world?
end
def self.from_node(node)
@ -28,7 +25,7 @@ class OldNode < ActiveRecord::Base
old_node.tags = node.tags
old_node.timestamp = node.timestamp
old_node.changeset_id = node.changeset_id
old_node.id = node.id
old_node.node_id = node.id
old_node.version = node.version
return old_node
end
@ -41,7 +38,7 @@ class OldNode < ActiveRecord::Base
def to_xml_node
el1 = XML::Node.new 'node'
el1['id'] = self.id.to_s
el1['id'] = self.node_id.to_s
el1['lat'] = self.lat.to_s
el1['lon'] = self.lon.to_s
el1['changeset'] = self.changeset.id.to_s
@ -69,13 +66,13 @@ class OldNode < ActiveRecord::Base
clear_aggregation_cache
clear_association_cache
#ok from here
@attributes.update(OldNode.find(:first, :conditions => ['id = ? AND timestamp = ? AND version = ?', self.id, self.timestamp, self.version]).instance_variable_get('@attributes'))
@attributes.update(OldNode.where(:node_id => self.node_id, :timestamp => self.timestamp, :version => self.version).first.instance_variable_get('@attributes'))
self.tags.each do |k,v|
tag = OldNodeTag.new
tag.k = k
tag.v = v
tag.id = self.id
tag.node_id = self.node_id
tag.version = self.version
tag.save!
end
@ -83,10 +80,10 @@ class OldNode < ActiveRecord::Base
def tags
unless @tags
@tags = Hash.new
OldNodeTag.find(:all, :conditions => ["id = ? AND version = ?", self.id, self.version]).each do |tag|
@tags[tag.k] = tag.v
end
@tags = Hash.new
OldNodeTag.where(:node_id => self.node_id, :version => self.version).each do |tag|
@tags[tag.k] = tag.v
end
end
@tags = Hash.new unless @tags
@tags

View file

@ -1,10 +1,11 @@
class OldNodeTag < ActiveRecord::Base
set_table_name 'node_tags'
set_primary_keys :node_id, :version, :k
belongs_to :user
belongs_to :old_node, :foreign_key => [:node_id, :version]
validates_presence_of :id, :version
validates_length_of :k, :v, :maximum => 255, :allow_blank => true
validates_uniqueness_of :id, :scope => [:k, :version]
validates_numericality_of :id, :version, :only_integer => true
validates_presence_of :old_node
validates_length_of :k, :maximum => 255, :allow_blank => true
validates_uniqueness_of :k, :scope => [:node_id, :version]
validates_length_of :v, :maximum => 255, :allow_blank => true
end

View file

@ -2,8 +2,12 @@ class OldRelation < ActiveRecord::Base
include ConsistencyValidations
set_table_name 'relations'
set_primary_keys :relation_id, :version
belongs_to :changeset
has_many :old_members, :class_name => 'OldRelationMember', :foreign_key => [:relation_id, :version], :order => :sequence_id
has_many :old_tags, :class_name => 'OldRelationTag', :foreign_key => [:relation_id, :version]
validates_associated :changeset
@ -12,7 +16,7 @@ class OldRelation < ActiveRecord::Base
old_relation.visible = relation.visible
old_relation.changeset_id = relation.changeset_id
old_relation.timestamp = relation.timestamp
old_relation.id = relation.id
old_relation.relation_id = relation.id
old_relation.version = relation.version
old_relation.members = relation.members
old_relation.tags = relation.tags
@ -25,7 +29,7 @@ class OldRelation < ActiveRecord::Base
save!
clear_aggregation_cache
clear_association_cache
@attributes.update(OldRelation.find(:first, :conditions => ['id = ? AND timestamp = ?', self.id, self.timestamp], :order => "version desc").instance_variable_get('@attributes'))
@attributes.update(OldRelation.where(:relation_id => self.relation_id, :timestamp => self.timestamp).order("version DESC").first.instance_variable_get('@attributes'))
# ok, you can touch from here on
@ -33,14 +37,14 @@ class OldRelation < ActiveRecord::Base
tag = OldRelationTag.new
tag.k = k
tag.v = v
tag.id = self.id
tag.relation_id = self.relation_id
tag.version = self.version
tag.save!
end
self.members.each_with_index do |m,i|
member = OldRelationMember.new
member.id = [self.id, self.version, i]
member.id = [self.relation_id, self.version, i]
member.member_type = m[0].classify
member.member_id = m[1]
member.member_role = m[2]
@ -50,20 +54,20 @@ class OldRelation < ActiveRecord::Base
def members
unless @members
@members = Array.new
OldRelationMember.find(:all, :conditions => ["id = ? AND version = ?", self.id, self.version], :order => "sequence_id").each do |m|
@members += [[m.type,m.id,m.role]]
end
@members = Array.new
OldRelationMember.where(:relation_id => self.relation_id, :version => self.version).order(:sequence_id).each do |m|
@members += [[m.type,m.id,m.role]]
end
end
@members
end
def tags
unless @tags
@tags = Hash.new
OldRelationTag.find(:all, :conditions => ["id = ? AND version = ?", self.id, self.version]).each do |tag|
@tags[tag.k] = tag.v
end
@tags = Hash.new
OldRelationTag.where(:relation_id => self.relation_id, :version => self.version).each do |tag|
@tags[tag.k] = tag.v
end
end
@tags = Hash.new unless @tags
@tags
@ -77,17 +81,6 @@ class OldRelation < ActiveRecord::Base
@tags = t
end
# has_many :relation_segments, :class_name => 'OldRelationSegment', :foreign_key => 'id'
# has_many :relation_tags, :class_name => 'OldRelationTag', :foreign_key => 'id'
def old_members
OldRelationMember.find(:all, :conditions => ['id = ? AND version = ?', self.id, self.version], :order => "sequence_id")
end
def old_tags
OldRelationTag.find(:all, :conditions => ['id = ? AND version = ?', self.id, self.version])
end
def to_xml
doc = OSM::API.new.get_xml_doc
doc.root << to_xml_node()
@ -96,7 +89,7 @@ class OldRelation < ActiveRecord::Base
def to_xml_node
el1 = XML::Node.new 'relation'
el1['id'] = self.id.to_s
el1['id'] = self.relation_id.to_s
el1['visible'] = self.visible.to_s
el1['timestamp'] = self.timestamp.xmlschema
if self.changeset.user.data_public?

View file

@ -1,8 +1,8 @@
class OldRelationMember < ActiveRecord::Base
set_table_name 'relation_members'
set_primary_keys :relation_id, :version, :sequence_id
set_primary_keys :id, :version, :sequence_id
belongs_to :relation, :foreign_key=> :id
belongs_to :old_relation, :foreign_key => [:relation_id, :version]
# A bit messy, referring to the current tables, should do for the data browser for now
belongs_to :member, :polymorphic => true
end

View file

@ -1,10 +1,11 @@
class OldRelationTag < ActiveRecord::Base
set_table_name 'relation_tags'
set_primary_keys :relation_id, :version, :k
belongs_to :old_relation, :foreign_key => [:relation_id, :version]
belongs_to :old_relation, :foreign_key => [:id, :version]
validates_presence_of :id, :version
validates_length_of :k, :v, :maximum => 255, :allow_blank => true
validates_uniqueness_of :id, :scope => [:k, :version]
validates_numericality_of :id, :version, :only_integer => true
validates_presence_of :old_relation
validates_length_of :k, :maximum => 255, :allow_blank => true
validates_uniqueness_of :k, :scope => [:relation_id, :version]
validates_length_of :v, :maximum => 255, :allow_blank => true
end

View file

@ -2,9 +2,13 @@ class OldWay < ActiveRecord::Base
include ConsistencyValidations
set_table_name 'ways'
set_primary_keys :way_id, :version
belongs_to :changeset
has_many :old_nodes, :class_name => 'OldWayNode', :foreign_key => [:way_id, :version]
has_many :old_tags, :class_name => 'OldWayTag', :foreign_key => [:way_id, :version]
validates_associated :changeset
def self.from_way(way)
@ -12,7 +16,7 @@ class OldWay < ActiveRecord::Base
old_way.visible = way.visible
old_way.changeset_id = way.changeset_id
old_way.timestamp = way.timestamp
old_way.id = way.id
old_way.way_id = way.id
old_way.version = way.version
old_way.nds = way.nds
old_way.tags = way.tags
@ -30,7 +34,7 @@ class OldWay < ActiveRecord::Base
save!
clear_aggregation_cache
clear_association_cache
@attributes.update(OldWay.find(:first, :conditions => ['id = ? AND timestamp = ?', self.id, self.timestamp], :order => "version desc").instance_variable_get('@attributes'))
@attributes.update(OldWay.where(:way_id => self.way_id, :timestamp => self.timestamp).order("version DESC").first.instance_variable_get('@attributes'))
# ok, you can touch from here on
@ -38,7 +42,7 @@ class OldWay < ActiveRecord::Base
tag = OldWayTag.new
tag.k = k
tag.v = v
tag.id = self.id
tag.way_id = self.way_id
tag.version = self.version
tag.save!
end
@ -46,7 +50,7 @@ class OldWay < ActiveRecord::Base
sequence = 1
self.nds.each do |n|
nd = OldWayNode.new
nd.id = [self.id, self.version, sequence]
nd.id = [self.way_id, self.version, sequence]
nd.node_id = n
nd.save!
sequence += 1
@ -55,20 +59,20 @@ class OldWay < ActiveRecord::Base
def nds
unless @nds
@nds = Array.new
OldWayNode.find(:all, :conditions => ["id = ? AND version = ?", self.id, self.version], :order => "sequence_id").each do |nd|
@nds += [nd.node_id]
end
@nds = Array.new
OldWayNode.where(:way_id => self.way_id, :version => self.version).order(:sequence_id).each do |nd|
@nds += [nd.node_id]
end
end
@nds
end
def tags
unless @tags
@tags = Hash.new
OldWayTag.find(:all, :conditions => ["id = ? AND version = ?", self.id, self.version]).each do |tag|
@tags[tag.k] = tag.v
end
@tags = Hash.new
OldWayTag.where(:way_id => self.way_id, :version => self.version).each do |tag|
@tags[tag.k] = tag.v
end
end
@tags = Hash.new unless @tags
@tags
@ -82,20 +86,9 @@ class OldWay < ActiveRecord::Base
@tags = t
end
# has_many :way_nodes, :class_name => 'OldWayNode', :foreign_key => 'id'
# has_many :way_tags, :class_name => 'OldWayTag', :foreign_key => 'id'
def old_nodes
OldWayNode.find(:all, :conditions => ['id = ? AND version = ?', self.id, self.version])
end
def old_tags
OldWayTag.find(:all, :conditions => ['id = ? AND version = ?', self.id, self.version])
end
def to_xml_node
el1 = XML::Node.new 'way'
el1['id'] = self.id.to_s
el1['id'] = self.way_id.to_s
el1['visible'] = self.visible.to_s
el1['timestamp'] = self.timestamp.xmlschema
if self.changeset.user.data_public?
@ -128,23 +121,23 @@ class OldWay < ActiveRecord::Base
# (i.e. is it visible? are we actually reverting to an earlier version?)
def get_nodes_undelete
points = []
self.nds.each do |n|
node=Node.find(n)
points << [node.lon, node.lat, n, node.version, node.tags_as_hash, node.visible]
points = []
self.nds.each do |n|
node = Node.find(n)
points << [node.lon, node.lat, n, node.version, node.tags_as_hash, node.visible]
end
points
points
end
def get_nodes_revert(timestamp)
points=[]
self.nds.each do |n|
oldnode=OldNode.find(:first, :conditions=>['id=? AND timestamp<=?',n,timestamp], :order=>"timestamp DESC")
curnode=Node.find(n)
id=n; reuse=curnode.visible
if oldnode.lat!=curnode.lat or oldnode.lon!=curnode.lon or oldnode.tags!=curnode.tags then
oldnode = OldNode.where('node_id = ? AND timestamp <= ?', n, timestamp).order("timestamp DESC").first
curnode = Node.find(n)
id = n; reuse = curnode.visible
if oldnode.lat != curnode.lat or oldnode.lon != curnode.lon or oldnode.tags != curnode.tags then
# node has changed: if it's in other ways, give it a new id
if curnode.ways-[self.id] then id=-1; reuse=false end
if curnode.ways-[self.way_id] then id=-1; reuse=false end
end
points << [oldnode.lon, oldnode.lat, id, curnode.version, oldnode.tags_as_hash, reuse]
end

View file

@ -1,10 +1,9 @@
class OldWayNode < ActiveRecord::Base
set_table_name 'way_nodes'
set_primary_keys :way_id, :version, :sequence_id
set_primary_keys :id, :version, :sequence_id
belongs_to :way, :foreign_key=> :id
# A bit messy, referring to current nodes, should do for the data browser for now
belongs_to :old_way, :foreign_key => [:way_id, :version]
# A bit messy, referring to current nodes and ways, should do for the data browser for now
belongs_to :node
belongs_to :way
end

View file

@ -1,10 +1,11 @@
class OldWayTag < ActiveRecord::Base
set_table_name 'way_tags'
set_primary_keys :way_id, :version, :k
belongs_to :old_way, :foreign_key => [:id, :version]
belongs_to :old_way, :foreign_key => [:way_id, :version]
validates_presence_of :id
validates_length_of :k, :v, :maximum => 255, :allow_blank => true
validates_uniqueness_of :id, :scope => [:k, :version]
validates_numericality_of :id, :version, :only_integer => true
validates_presence_of :old_way
validates_length_of :k, :maximum => 255, :allow_blank => true
validates_uniqueness_of :k, :scope => [:way_id, :version]
validates_length_of :v, :maximum => 255, :allow_blank => true
end

View file

@ -7,10 +7,10 @@ class Relation < ActiveRecord::Base
belongs_to :changeset
has_many :old_relations, :foreign_key => 'id', :order => 'version'
has_many :old_relations, :order => 'version'
has_many :relation_members, :foreign_key => 'id', :order => 'sequence_id'
has_many :relation_tags, :foreign_key => 'id'
has_many :relation_members, :order => 'sequence_id'
has_many :relation_tags
has_many :containing_relation_members, :class_name => "RelationMember", :as => :member
has_many :containing_relations, :class_name => "Relation", :through => :containing_relation_members, :source => :relation, :extend => ObjectFinder
@ -23,6 +23,12 @@ class Relation < ActiveRecord::Base
validates_numericality_of :changeset_id, :version, :integer_only => true
validates_associated :changeset
scope :visible, where(:visible => true)
scope :invisible, where(:visible => false)
scope :nodes, lambda { |*ids| joins(:relation_members).where(:current_relation_members => { :member_type => "Node", :member_id => ids }) }
scope :ways, lambda { |*ids| joins(:relation_members).where(:current_relation_members => { :member_type => "Way", :member_id => ids }) }
scope :relations, lambda { |*ids| joins(:relation_members).where(:current_relation_members => { :member_type => "Relation", :member_id => ids }) }
TYPES = ["node", "way", "relation"]
def self.from_xml(xml, create=false)
@ -148,36 +154,6 @@ class Relation < ActiveRecord::Base
return el1
end
def self.find_for_nodes(ids, options = {})
if ids.empty?
return []
else
self.with_scope(:find => { :joins => "INNER JOIN current_relation_members AS crm ON crm.id = current_relations.id", :conditions => "crm.member_type = 'Node' AND crm.member_id IN (#{ids.join(',')})" }) do
return self.find(:all, options)
end
end
end
def self.find_for_ways(ids, options = {})
if ids.empty?
return []
else
self.with_scope(:find => { :joins => "INNER JOIN current_relation_members AS crm ON crm.id = current_relations.id", :conditions => "crm.member_type = 'Way' AND crm.member_id IN (#{ids.join(',')})" }) do
return self.find(:all, options)
end
end
end
def self.find_for_relations(ids, options = {})
if ids.empty?
return []
else
self.with_scope(:find => { :joins => "INNER JOIN current_relation_members AS crm ON crm.id = current_relations.id", :conditions => "crm.member_type = 'Relation' AND crm.member_id IN (#{ids.join(',')})" }) do
return self.find(:all, options)
end
end
end
# FIXME is this really needed?
def members
unless @members
@ -244,8 +220,7 @@ class Relation < ActiveRecord::Base
self.lock!
check_consistency(self, new_relation, user)
# This will check to see if this relation is used by another relation
rel = RelationMember.find(:first, :joins => :relation,
:conditions => [ "visible = ? AND member_type='Relation' and member_id=? ", true, self.id ])
rel = RelationMember.joins(:relation).where("visible = ? AND member_type = 'Relation' and member_id = ? ", true, self.id).first
raise OSM::APIPreconditionFailedError.new("The relation #{new_relation.id} is used in relation #{rel.relation.id}.") unless rel.nil?
self.changeset_id = new_relation.changeset_id
@ -303,7 +278,7 @@ class Relation < ActiveRecord::Base
# use reflection to look up the appropriate class
model = Kernel.const_get(m[0].capitalize)
# get the element with that ID
element = model.find(:first, :conditions =>["id = ?", m[1]])
element = model.where(:id => m[1]).first
# and check that it is OK to use.
unless element and element.visible? and element.preconditions_ok?
@ -373,12 +348,12 @@ class Relation < ActiveRecord::Base
# if there are left-over tags then they are new and will have to
# be added.
tags_changed |= (not tags.empty?)
RelationTag.delete_all(:id => self.id)
RelationTag.delete_all(:relation_id => self.id)
self.tags.each do |k,v|
tag = RelationTag.new
tag.relation_id = self.id
tag.k = k
tag.v = v
tag.id = self.id
tag.save!
end
@ -403,10 +378,11 @@ class Relation < ActiveRecord::Base
# members may be in a different order and i don't feel like implementing
# a longest common subsequence algorithm to optimise this.
members = self.members
RelationMember.delete_all(:id => self.id)
RelationMember.delete_all(:relation_id => self.id)
members.each_with_index do |m,i|
mem = RelationMember.new
mem.id = [self.id, i]
mem.relation_id = self.id
mem.sequence_id = i
mem.member_type = m[0]
mem.member_id = m[1]
mem.member_role = m[2]

View file

@ -1,24 +1,26 @@
class RelationMember < ActiveRecord::Base
set_table_name 'current_relation_members'
set_primary_keys :id, :sequence_id
set_table_name 'current_relation_members'
set_primary_keys :relation_id, :sequence_id
belongs_to :relation
belongs_to :member, :polymorphic => true
belongs_to :relation, :foreign_key => :id
def after_find
self[:member_class] = self.member_type.classify
end
def after_initialize
self[:member_class] = self.member_type.classify unless self.member_type.nil?
end
def before_save
self.member_type = self[:member_class].classify
end
after_find :set_class_from_type
after_initialize :set_class_from_type
before_save :set_type_from_class
def member_type=(type)
self[:member_type] = type
self[:member_class] = type.capitalize
end
private
def set_class_from_type
self[:member_class] = self.member_type.classify unless self.member_type.nil?
end
def set_type_from_class
self.member_type = self[:member_class].classify
end
end

View file

@ -1,10 +1,11 @@
class RelationTag < ActiveRecord::Base
set_table_name 'current_relation_tags'
set_primary_keys :relation_id, :k
belongs_to :relation, :foreign_key => 'id'
belongs_to :relation
validates_presence_of :id
validates_length_of :k, :v, :maximum => 255, :allow_blank => true
validates_uniqueness_of :id, :scope => :k
validates_numericality_of :id, :only_integer => true
validates_presence_of :relation
validates_length_of :k, :maximum => 255, :allow_blank => true
validates_uniqueness_of :k, :scope => :relation_id
validates_length_of :v, :maximum => 255, :allow_blank => true
end

View file

@ -6,7 +6,7 @@ class RequestToken < OauthToken
return false if authorized?
self.user = user
self.authorized_at = Time.now
self.verifier = OAuth::Helper.generate_key(16)[0,20] unless oauth10?
self.verifier = OAuth::Helper.generate_key(20)[0,20] unless oauth10?
self.save
end
@ -36,7 +36,7 @@ class RequestToken < OauthToken
end
def oob?
self.callback_url=='oob'
callback_url.nil? || callback_url.downcase == 'oob'
end
def oauth10?

View file

@ -3,9 +3,9 @@ class SpamObserver < ActiveRecord::Observer
def after_save(record)
case
when record.is_a?(User): user = record
when record.is_a?(DiaryEntry): user = record.user
when record.is_a?(DiaryComment): user = record.user
when record.is_a?(User) then user = record
when record.is_a?(DiaryEntry) then user = record.user
when record.is_a?(DiaryComment) then user = record.user
end
if user.status == "active" and user.spam_score > SPAM_THRESHOLD

View file

@ -1,6 +1,14 @@
class Trace < ActiveRecord::Base
set_table_name 'gpx_files'
belongs_to :user
has_many :tags, :class_name => 'Tracetag', :foreign_key => 'gpx_id', :dependent => :delete_all
has_many :points, :class_name => 'Tracepoint', :foreign_key => 'gpx_id', :dependent => :delete_all
scope :visible, where(:visible => true)
scope :visible_to, lambda { |u| visible.where("visibility IN ('public', 'identifiable') OR user_id = ?", u) }
scope :public, where(:visibility => ["public", "identifiable"])
validates_presence_of :user_id, :name, :timestamp
validates_presence_of :description, :on => :create
validates_length_of :name, :maximum => 255
@ -9,10 +17,6 @@ class Trace < ActiveRecord::Base
validates_inclusion_of :inserted, :in => [ true, false ]
validates_inclusion_of :visibility, :in => ["private", "public", "trackable", "identifiable"]
belongs_to :user
has_many :tags, :class_name => 'Tracetag', :foreign_key => 'gpx_id', :dependent => :delete_all
has_many :points, :class_name => 'Tracepoint', :foreign_key => 'gpx_id', :dependent => :delete_all
def destroy
super
FileUtils.rm_f(trace_name)
@ -262,8 +266,8 @@ class Trace < ActiveRecord::Base
# If there are any existing points for this trace then delete
# them - we check for existing points first to avoid locking
# the table in the common case where there aren't any.
if Tracepoint.find(:first, :conditions => ['gpx_id = ?', self.id])
Tracepoint.delete_all(['gpx_id = ?', self.id])
if Tracepoint.where(:gpx_id => self.id).exists?
Tracepoint.delete_all(:gpx_id => self.id)
end
gpx.points do |point|

View file

@ -8,6 +8,7 @@ class User < ActiveRecord::Base
has_many :new_messages, :class_name => "Message", :foreign_key => :to_user_id, :conditions => { :to_user_visible => true, :message_read => false }, :order => 'sent_on DESC'
has_many :sent_messages, :class_name => "Message", :foreign_key => :from_user_id, :conditions => { :from_user_visible => true }, :order => 'sent_on DESC'
has_many :friends, :include => :befriendee, :conditions => "users.status IN ('active', 'confirmed')"
has_many :friend_users, :through => :friends, :source => :befriendee
has_many :tokens, :class_name => "UserToken"
has_many :preferences, :class_name => "UserPreference"
has_many :changesets, :order => 'created_at DESC'
@ -15,14 +16,18 @@ class User < ActiveRecord::Base
has_many :client_applications
has_many :oauth_tokens, :class_name => "OauthToken", :order => "authorized_at desc", :include => [:client_application]
has_many :active_blocks, :class_name => "UserBlock", :conditions => ['user_blocks.ends_at > \'#{Time.now.getutc.xmlschema(5)}\' or user_blocks.needs_view']
has_many :active_blocks, :class_name => "UserBlock", :conditions => proc { [ "user_blocks.ends_at > :ends_at or user_blocks.needs_view", { :ends_at => Time.now.getutc } ] }
has_many :roles, :class_name => "UserRole"
scope :visible, where(:status => ["pending", "active", "confirmed"])
scope :active, where(:status => ["active", "confirmed"])
scope :public, where(:data_public => true)
validates_presence_of :email, :display_name
validates_confirmation_of :email#, :message => ' addresses must match'
validates_confirmation_of :pass_crypt#, :message => ' must match the confirmation password'
validates_uniqueness_of :display_name, :allow_nil => true
validates_uniqueness_of :email
validates_uniqueness_of :display_name, :allow_nil => true, :case_sensitive => false, :if => Proc.new { |u| u.display_name_changed? }
validates_uniqueness_of :email, :case_sensitive => false, :if => Proc.new { |u| u.email_changed? }
validates_uniqueness_of :openid_url, :allow_nil => true
validates_length_of :pass_crypt, :within => 8..255
validates_length_of :display_name, :within => 3..255, :allow_nil => true
@ -36,27 +41,26 @@ class User < ActiveRecord::Base
validates_numericality_of :home_zoom, :only_integer => true, :allow_nil => true
validates_inclusion_of :preferred_editor, :in => Editors::ALL_EDITORS, :allow_nil => true
after_initialize :set_creation_time
before_save :encrypt_password
file_column :image, :magick => { :geometry => "100x100>" }
def after_initialize
self.creation_time = Time.now.getutc unless self.attribute_present?(:creation_time)
end
def encrypt_password
if pass_crypt_confirmation
self.pass_salt = OSM::make_token(8)
self.pass_crypt = OSM::encrypt_password(pass_crypt, pass_salt)
end
end
def self.authenticate(options)
if options[:username] and options[:password]
user = find(:first, :conditions => ["email = ? OR display_name = ?", options[:username], options[:username]])
user = where("email = ? OR display_name = ?", options[:username], options[:username]).first
if user.nil?
users = where("LOWER(email) = LOWER(?) OR LOWER(display_name) = LOWER(?)", options[:username], options[:username])
if users.count == 1
user = users.first
end
end
user = nil if user and user.pass_crypt != OSM::encrypt_password(options[:password], user.pass_salt)
elsif options[:token]
token = UserToken.find(:first, :include => :user, :conditions => ["user_tokens.token = ?", options[:token]])
token = UserToken.find_by_token(options[:token])
user = token.user if token
end
@ -101,7 +105,7 @@ class User < ActiveRecord::Base
end
def preferred_language
languages.find { |l| Language.find(:first, :conditions => { :code => l }) }
languages.find { |l| Language.exists?(:code => l) }
end
def preferred_language_from(array)
@ -113,9 +117,7 @@ class User < ActiveRecord::Base
gc = OSM::GreatCircle.new(self.home_lat, self.home_lon)
bounds = gc.bounds(radius)
sql_for_distance = gc.sql_for_distance("home_lat", "home_lon")
nearby = User.find(:all,
:conditions => ["id != ? AND status IN (\'active\', \'confirmed\') AND data_public = ? AND #{sql_for_distance} <= ?", id, true, radius],
:order => sql_for_distance, :limit => num)
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)
else
nearby = []
end
@ -191,8 +193,8 @@ class User < ActiveRecord::Base
##
# return a spam score for a user
def spam_score
changeset_score = self.changesets.find(:all, :limit => 10).length * 50
trace_score = self.traces.find(:all, :limit => 10).length * 50
changeset_score = self.changesets.limit(10).length * 50
trace_score = self.traces.limit(10).length * 50
diary_entry_score = self.diary_entries.inject(0) { |s,e| s += OSM.spam_score(e.body) }
diary_comment_score = self.diary_comments.inject(0) { |s,e| s += OSM.spam_score(e.body) }
@ -210,4 +212,17 @@ class User < ActiveRecord::Base
def access_token(application_key)
return ClientApplication.find_by_key(application_key).access_token_for_user(self)
end
private
def set_creation_time
self.creation_time = Time.now.getutc unless self.attribute_present?(:creation_time)
end
def encrypt_password
if pass_crypt_confirmation
self.pass_salt = OSM::make_token(8)
self.pass_crypt = OSM::encrypt_password(pass_crypt, pass_salt)
end
end
end

View file

@ -29,7 +29,7 @@ class UserBlock < ActiveRecord::Base
# block. this should be caught and dealt with in the controller,
# but i've also included it here just in case.
def moderator_permissions
errors.add_to_base(I18n.t('user_block.model.non_moderator_update')) if creator_id_changed? and !creator.moderator?
errors.add_to_base(I18n.t('user_block.model.non_moderator_revoke')) unless revoker_id.nil? or revoker.moderator?
errors.add(:base, I18n.t('user_block.model.non_moderator_update')) if creator_id_changed? and !creator.moderator?
errors.add(:base, I18n.t('user_block.model.non_moderator_revoke')) unless revoker_id.nil? or revoker.moderator?
end
end

View file

@ -1,7 +1,11 @@
class UserToken < ActiveRecord::Base
belongs_to :user
def after_initialize
after_initialize :set_defaults
private
def set_defaults
self.token = OSM::make_token() if self.token.blank?
self.expiry = 1.week.from_now if self.expiry.blank?
end

View file

@ -7,12 +7,12 @@ class Way < ActiveRecord::Base
belongs_to :changeset
has_many :old_ways, :foreign_key => 'id', :order => 'version'
has_many :old_ways, :order => 'version'
has_many :way_nodes, :foreign_key => 'id', :order => 'sequence_id'
has_many :way_nodes, :order => 'sequence_id'
has_many :nodes, :through => :way_nodes, :order => 'sequence_id'
has_many :way_tags, :foreign_key => 'id'
has_many :way_tags
has_many :containing_relation_members, :class_name => "RelationMember", :as => :member
has_many :containing_relations, :class_name => "Relation", :through => :containing_relation_members, :source => :relation, :extend => ObjectFinder
@ -25,6 +25,9 @@ class Way < ActiveRecord::Base
validates_numericality_of :id, :on => :update, :integer_only => true
validates_associated :changeset
scope :visible, where(:visible => true)
scope :invisible, where(:visible => false)
# Read in xml as text and return it's Way object representation
def self.from_xml(xml, create=false)
begin
@ -202,7 +205,7 @@ class Way < ActiveRecord::Base
def bbox
lons = nodes.collect { |n| n.longitude }
lats = nodes.collect { |n| n.latitude }
[ lons.min, lats.min, lons.max, lats.max ]
BoundingBox.new(lons.min, lats.min, lons.max, lats.max)
end
def update_from(new_way, user)
@ -243,7 +246,7 @@ class Way < ActiveRecord::Base
new_nds = (self.nds - old_nodes).sort.uniq
unless new_nds.empty?
db_nds = Node.find(:all, :conditions => { :id => new_nds, :visible => true })
db_nds = Node.where(:id => new_nds, :visible => true)
if db_nds.length < new_nds.length
missing = new_nds - db_nds.collect { |n| n.id }
@ -265,10 +268,9 @@ class Way < ActiveRecord::Base
Way.transaction do
self.lock!
check_consistency(self, new_way, user)
rel = RelationMember.find(:first, :joins => :relation,
:conditions => [ "visible = ? AND member_type='Way' and member_id=? ", true, self.id])
raise OSM::APIPreconditionFailedError.new("Way #{self.id} still used by relation #{rel.relation.id}.") if rel
rels = Relation.joins(:relation_members).where(:visible => true, :current_relation_members => { :member_type => "Way", :member_id => id }).order(:id)
raise OSM::APIPreconditionFailedError.new("Way #{self.id} is still used by relations #{rels.collect { |r| r.id }.join(",")}.") unless rels.empty?
self.changeset_id = new_way.changeset_id
self.changeset = new_way.changeset
@ -318,17 +320,17 @@ class Way < ActiveRecord::Base
self.save!
tags = self.tags
WayTag.delete_all(['id = ?', self.id])
WayTag.delete_all(:way_id => self.id)
tags.each do |k,v|
tag = WayTag.new
tag.way_id = self.id
tag.k = k
tag.v = v
tag.id = self.id
tag.save!
end
nds = self.nds
WayNode.delete_all(['id = ?', self.id])
WayNode.delete_all(:way_id => self.id)
sequence = 1
nds.each do |n|
nd = WayNode.new
@ -356,5 +358,4 @@ class Way < ActiveRecord::Base
cs.save!
end
end
end

View file

@ -1,8 +1,7 @@
class WayNode < ActiveRecord::Base
set_table_name 'current_way_nodes'
set_primary_keys :way_id, :sequence_id
set_primary_keys :id, :sequence_id
belongs_to :way
belongs_to :node
belongs_to :way, :foreign_key => :id
end

View file

@ -1,14 +1,11 @@
class WayTag < ActiveRecord::Base
set_table_name 'current_way_tags'
set_primary_keys :way_id, :k
# False multipart keys. The following would be a hack:
# set_primary_keys :id, :k, :v
# FIXME add a real multipart key to waytags so that we can do eager loadin
belongs_to :way, :foreign_key => 'id'
belongs_to :way
validates_presence_of :id
validates_length_of :k, :v, :maximum => 255, :allow_blank => true
validates_uniqueness_of :id, :scope => :k
validates_numericality_of :id, :only_integer => true
validates_presence_of :way
validates_length_of :k, :maximum => 255, :allow_blank => true
validates_uniqueness_of :k, :scope => :way_id
validates_length_of :v, :maximum => 255, :allow_blank => true
end