Merge branch 'master' into moderation

This commit is contained in:
Andy Allan 2017-07-12 10:16:11 +01:00
commit dbd88d893f
785 changed files with 365807 additions and 212676 deletions

View file

@ -5,4 +5,6 @@ Grant Slater <openstreetmap@firefishy.com> <github@firefishy.com>
Harry Wood <git@harrywood.co.uk> <mail@harrywood.co.uk> <github@onlineanimals.co.uk>
Kai Krueger <kakrueger@gmail.com> <kai@aiputerlx.(none)>
Michael Glanznig <nebulon42@yandex.com>
Petr Kadlec <mormegil@centrum.cz>
Richard Fairhurst <richard@systemeD.net> <richard@systemed.net>
Simon Poole <simon@poole.ch> <simon@rails-dev.poole.ch>

View file

@ -1,20 +1,44 @@
inherit_from: .rubocop_todo.yml
AllCops:
Include:
- '**/*.gemspec'
- '**/*.podspec'
- '**/*.jbuilder'
- '**/*.rake'
- '**/*.opal'
- '**/config.ru'
- '**/Gemfile'
- '**/Rakefile'
- '**/Capfile'
- '**/Guardfile'
- '**/Podfile'
- '**/Thorfile'
- '**/Vagrantfile'
- '**/Berksfile'
- '**/Cheffile'
- '**/Vagabondfile'
- '**/Fastfile'
- '**/*.builder'
Rails:
Enabled: true
Layout/ExtraSpacing:
AllowForAlignment: true
Style/BracesAroundHashParameters:
EnforcedStyle: context_dependent
Style/ExtraSpacing:
AllowForAlignment: true
Style/FileName:
Exclude:
- 'script/deliver-message'
- 'script/locale/reload-languages'
- 'script/update-spam-blocks'
Style/FormatStringToken:
EnforcedStyle: template
Style/IfInsideElse:
Enabled: false
@ -33,3 +57,22 @@ Style/HashSyntax:
Style/StringLiterals:
EnforcedStyle: double_quotes
Style/SymbolArray:
EnforcedStyle: brackets
Rails/ApplicationRecord:
Enabled: false
Rails/HttpPositionalArguments:
Enabled: false
Rails/SkipsModelValidations:
Exclude:
- 'db/migrate/*.rb'
- 'app/controllers/user_controller.rb'
Lint/PercentStringArray:
Exclude:
- 'config/initializers/secure_headers.rb'
- 'app/controllers/site_controller.rb'

View file

@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2016-07-13 09:47:52 +0100 using RuboCop version 0.41.2.
# on 2016-10-20 21:45:27 +0100 using RuboCop version 0.44.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
@ -14,11 +14,11 @@ Lint/AmbiguousOperator:
- 'test/lib/bounding_box_test.rb'
- 'test/lib/country_test.rb'
# Offense count: 115
# Offense count: 117
Lint/AmbiguousRegexpLiteral:
Enabled: false
# Offense count: 29
# Offense count: 30
# Configuration parameters: AllowSafeAssignment.
Lint/AssignmentInCondition:
Exclude:
@ -43,30 +43,40 @@ Lint/HandleExceptions:
- 'app/controllers/user_controller.rb'
- 'config/initializers/session.rb'
# Offense count: 616
Metrics/AbcSize:
Max: 277
# Offense count: 2
Lint/ShadowingOuterLocalVariable:
Exclude:
- 'app/views/changeset/list.atom.builder'
# Offense count: 11
# Offense count: 630
Metrics/AbcSize:
Max: 280
# Offense count: 35
# Configuration parameters: CountComments.
Metrics/BlockLength:
Max: 295
# Offense count: 12
Metrics/BlockNesting:
Max: 5
# Offense count: 62
# Configuration parameters: CountComments.
Metrics/ClassLength:
Max: 1650
Max: 1790
# Offense count: 67
# Offense count: 69
Metrics/CyclomaticComplexity:
Max: 20
# Offense count: 2485
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes.
# Offense count: 2826
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives.
# URISchemes: http, https
Metrics/LineLength:
Max: 962
Max: 1072
# Offense count: 596
# Offense count: 612
# Configuration parameters: CountComments.
Metrics/MethodLength:
Max: 179
@ -74,14 +84,14 @@ Metrics/MethodLength:
# Offense count: 1
# Configuration parameters: CountComments.
Metrics/ModuleLength:
Max: 139
Max: 147
# Offense count: 4
# Configuration parameters: CountKeywordArgs.
Metrics/ParameterLists:
Max: 9
# Offense count: 70
# Offense count: 71
Metrics/PerceivedComplexity:
Max: 23
@ -101,6 +111,17 @@ Rails/HasAndBelongsToMany:
- 'app/models/changeset.rb'
- 'app/models/user.rb'
# Offense count: 5
# Configuration parameters: Include.
# Include: db/migrate/*.rb
Rails/NotNullColumn:
Exclude:
- 'db/migrate/002_cleanup_osm_db.rb'
- 'db/migrate/020_populate_node_tags_and_remove.rb'
- 'db/migrate/021_move_to_innodb.rb'
- 'db/migrate/025_add_end_time_to_changesets.rb'
- 'db/migrate/20120404205604_add_user_and_description_to_redaction.rb'
# Offense count: 17
Rails/OutputSafety:
Exclude:
@ -115,7 +136,7 @@ Rails/OutputSafety:
- 'lib/rich_text.rb'
- 'test/helpers/application_helper_test.rb'
# Offense count: 65
# Offense count: 74
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: strict, flexible
Rails/TimeZone:
@ -135,10 +156,17 @@ Style/AsciiComments:
Exclude:
- 'test/models/message_test.rb'
# Offense count: 217
# Offense count: 220
Style/Documentation:
Enabled: false
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: MaxLineLength.
Style/IfUnlessModifier:
Exclude:
- 'app/controllers/way_controller.rb'
# Offense count: 60
# Cop supports --auto-correct.
Style/LineEndConcatenation:
@ -154,22 +182,11 @@ Style/LineEndConcatenation:
- 'test/controllers/relation_controller_test.rb'
- 'test/controllers/way_controller_test.rb'
# Offense count: 69
# Offense count: 71
# Cop supports --auto-correct.
Style/NumericLiterals:
MinDigits: 11
# Offense count: 38
# Cop supports --auto-correct.
Style/PerlBackrefs:
Exclude:
- 'app/controllers/amf_controller.rb'
- 'app/helpers/browse_helper.rb'
- 'config/initializers/paperclip.rb'
- 'lib/id.rb'
- 'lib/potlatch.rb'
- 'test/lib/i18n_test.rb'
# Offense count: 8
# Configuration parameters: NamePrefix, NamePrefixBlacklist, NameWhitelist.
# NamePrefix: is_, has_, have_
@ -197,15 +214,3 @@ Style/RaiseArgs:
Style/RescueModifier:
Exclude:
- 'app/helpers/browse_helper.rb'
# Offense count: 8
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: single_quotes, double_quotes
Style/StringLiteralsInInterpolation:
Exclude:
- 'app/controllers/amf_controller.rb'
- 'app/models/node.rb'
- 'app/models/way.rb'
- 'lib/migrate.rb'
- 'test/controllers/changeset_controller_test.rb'

View file

@ -26,4 +26,4 @@ before_script:
script:
- bundle exec rubocop -f fuubar
- bundle exec rake jshint
- bundle exec rake test
- bundle exec rake test:db

View file

@ -6,7 +6,7 @@
When writing code it is generally a good idea to try and match your
formatting to that of any existing code in the same file, or to other
similar files if you are writing new code. Consistency of layout is
far more important that the layout itself as it makes reading code
far more important than the layout itself as it makes reading code
much easier.
One golden rule of formatting -- please don't use tabs in your code

65
Gemfile
View file

@ -1,7 +1,7 @@
source "https://rubygems.org"
# Require rails
gem "rails", "4.2.7"
gem "rails", "5.0.4"
# Require things which have moved to gems in ruby 1.9
gem "bigdecimal", "~> 1.1.0", :platforms => :ruby_19
@ -22,7 +22,7 @@ gem "sass-rails", "~> 5.0"
gem "uglifier", ">= 1.3.0"
# Use CoffeeScript for .js.coffee assets and views
gem "coffee-rails", "~> 4.1.0"
gem "coffee-rails", "~> 4.2"
# Use jquery as the JavaScript library
gem "jquery-rails"
@ -38,32 +38,34 @@ gem "r2"
gem "autoprefixer-rails"
# Use image_optim to optimise images
gem "image_optim", ">= 0.22.0"
gem "image_optim_rails"
# Load rails plugins
gem "rails-i18n", "~> 4.0.0"
gem "dynamic_form"
gem "rinku", ">= 1.2.2", :require => "rails_rinku"
gem "oauth-plugin", ">= 0.5.1"
gem "validates_email_format_of", ">= 1.5.1"
gem "composite_primary_keys", "~> 8.1.0"
gem "http_accept_language", "~> 2.0.0"
gem "paperclip", "~> 4.0"
gem "deadlock_retry", ">= 1.2.0"
gem "i18n-js", ">= 3.0.0.rc10"
gem "rack-cors"
gem "actionpack-page_caching"
gem "composite_primary_keys", "~> 9.0.7"
gem "deadlock_retry", ">= 1.2.0"
gem "dynamic_form"
gem "http_accept_language", "~> 2.0.0"
gem "i18n-js", ">= 3.0.0"
gem "oauth-plugin", ">= 0.5.1"
gem "paperclip", "~> 4.0"
gem "rack-cors"
gem "rails-i18n", "~> 4.0.0"
gem "record_tag_helper"
gem "rinku", ">= 1.2.2", :require => "rails_rinku"
gem "validates_email_format_of", ">= 1.5.1"
# Sanitise URIs
gem "rack-uri_sanitizer"
# Omniauth for authentication
gem "omniauth"
gem "omniauth-openid"
gem "omniauth-google-oauth2", ">= 0.2.7"
gem "omniauth-facebook"
gem "omniauth-windowslive"
gem "omniauth-github"
gem "omniauth-google-oauth2", ">= 0.2.7"
gem "omniauth-mediawiki", ">= 0.0.3"
gem "omniauth-openid"
gem "omniauth-windowslive"
# Markdown formatting support
gem "redcarpet"
@ -75,8 +77,8 @@ gem "aasm"
gem "libxml-ruby", ">= 2.0.5", :require => "libxml"
# Use for HTML sanitisation
gem "sanitize"
gem "htmlentities"
gem "sanitize"
# Load SystemTimer for implementing request timeouts
gem "SystemTimer", ">= 1.1.3", :require => "system_timer", :platforms => :ruby_18
@ -84,33 +86,44 @@ gem "SystemTimer", ">= 1.1.3", :require => "system_timer", :platforms => :ruby_1
# Load faraday for mockable HTTP client
gem "faraday"
# Load httpclient and soap4r for SOAP support for Quova GeoIP queries
gem "httpclient"
gem "soap4r-ruby1.9"
# Load geoip for querying Maxmind GeoIP database
gem "geoip"
# Load rotp to generate TOTP tokens
gem "rotp"
# Load memcache client in case we are using it
gem "dalli"
gem "kgio"
# Load secure_headers for Content-Security-Policy support
gem "secure_headers"
# Load canonical-rails to generate canonical URLs
gem "canonical-rails"
# Used to generate logstash friendly log files
gem "logstasher"
# Gems useful for development
group :development do
gem "listen"
gem "vendorer"
end
# Gems needed for running tests
group :test do
gem "rubocop"
gem "timecop"
gem "minitest", "~> 5.1", :platforms => [:ruby_19, :ruby_20]
gem "rails-controller-testing"
gem "rubocop"
gem "webmock"
end
# Needed in development as well so rake can see konacha tasks
group :development, :test do
gem "jshint"
gem "konacha"
gem "poltergeist"
gem "coveralls", :require => false
gem "factory_girl_rails"
gem "jshint"
# gem "konacha"
gem "poltergeist"
end

View file

@ -3,79 +3,84 @@ GEM
specs:
SystemTimer (1.2.3)
aasm (4.1.0)
actionmailer (4.2.7)
actionpack (= 4.2.7)
actionview (= 4.2.7)
activejob (= 4.2.7)
actioncable (5.0.4)
actionpack (= 5.0.4)
nio4r (>= 1.2, < 3.0)
websocket-driver (~> 0.6.1)
actionmailer (5.0.4)
actionpack (= 5.0.4)
actionview (= 5.0.4)
activejob (= 5.0.4)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 1.0, >= 1.0.5)
actionpack (4.2.7)
actionview (= 4.2.7)
activesupport (= 4.2.7)
rack (~> 1.6)
rack-test (~> 0.6.2)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-dom-testing (~> 2.0)
actionpack (5.0.4)
actionview (= 5.0.4)
activesupport (= 5.0.4)
rack (~> 2.0)
rack-test (~> 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionpack-page_caching (1.0.2)
actionpack (>= 4.0.0, < 5)
actionview (4.2.7)
activesupport (= 4.2.7)
actionpack-page_caching (1.1.0)
actionpack (>= 4.0.0, < 6)
actionview (5.0.4)
activesupport (= 5.0.4)
builder (~> 3.1)
erubis (~> 2.7.0)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
activejob (4.2.7)
activesupport (= 4.2.7)
globalid (>= 0.3.0)
activemodel (4.2.7)
activesupport (= 4.2.7)
builder (~> 3.1)
activerecord (4.2.7)
activemodel (= 4.2.7)
activesupport (= 4.2.7)
arel (~> 6.0)
activesupport (4.2.7)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
activejob (5.0.4)
activesupport (= 5.0.4)
globalid (>= 0.3.6)
activemodel (5.0.4)
activesupport (= 5.0.4)
activerecord (5.0.4)
activemodel (= 5.0.4)
activesupport (= 5.0.4)
arel (~> 7.0)
activesupport (5.0.4)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (~> 0.7)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
addressable (2.4.0)
arel (6.0.3)
addressable (2.5.1)
public_suffix (~> 2.0, >= 2.0.2)
arel (7.1.4)
ast (2.3.0)
autoprefixer-rails (6.3.7)
autoprefixer-rails (7.1.1.2)
execjs
bigdecimal (1.1.0)
builder (3.2.2)
capybara (2.7.1)
builder (3.2.3)
canonical-rails (0.2.0)
rails (>= 4.1, < 5.2)
capybara (2.14.3)
addressable
mime-types (>= 1.16)
nokogiri (>= 1.3.3)
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (~> 2.0)
climate_control (0.0.3)
activesupport (>= 3.0)
climate_control (0.2.0)
cliver (0.3.2)
cocaine (0.5.8)
climate_control (>= 0.0.3, < 1.0)
coffee-rails (4.1.1)
coffee-rails (4.2.2)
coffee-script (>= 2.2.0)
railties (>= 4.0.0, < 5.1.x)
railties (>= 4.0.0)
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.10.0)
colorize (0.8.1)
composite_primary_keys (8.1.3)
activerecord (~> 4.2.0)
concurrent-ruby (1.0.2)
coveralls (0.8.14)
coffee-script-source (1.12.2)
composite_primary_keys (9.0.7)
activerecord (~> 5.0.0)
concurrent-ruby (1.0.5)
coveralls (0.8.21)
json (>= 1.8, < 3)
simplecov (~> 0.12.0)
simplecov (~> 0.14.1)
term-ansicolor (~> 1.3)
thor (~> 0.19.1)
tins (~> 1.6.0)
thor (~> 0.19.4)
tins (~> 1.6)
crack (0.4.3)
safe_yaml (~> 1.0.0)
crass (1.0.2)
dalli (2.7.6)
deadlock_retry (1.2.0)
@ -83,76 +88,83 @@ GEM
dynamic_form (1.1.4)
erubis (2.7.0)
execjs (2.7.0)
exifr (1.2.4)
faraday (0.9.2)
exifr (1.2.5)
factory_girl (4.8.0)
activesupport (>= 3.0.0)
factory_girl_rails (4.8.0)
factory_girl (~> 4.8.0)
railties (>= 3.0.0)
faraday (0.12.1)
multipart-post (>= 1.2, < 3)
fspath (2.1.1)
globalid (0.3.6)
activesupport (>= 4.1.0)
hashie (3.4.4)
ffi (1.9.18)
fspath (3.1.0)
geoip (1.6.3)
globalid (0.4.0)
activesupport (>= 4.2.0)
hashdiff (0.3.4)
hashie (3.5.5)
htmlentities (4.3.4)
http_accept_language (2.0.5)
httpclient (2.8.0)
i18n (0.7.0)
i18n-js (3.0.0.rc13)
i18n (0.8.4)
i18n-js (3.0.0)
i18n (~> 0.6, >= 0.6.6)
image_optim (0.22.1)
image_optim (0.24.3)
exifr (~> 1.2, >= 1.2.2)
fspath (~> 2.1)
image_size (~> 1.3)
fspath (~> 3.0)
image_size (~> 1.5)
in_threads (~> 1.3)
progress (~> 3.0, >= 3.0.1)
image_size (1.4.2)
in_threads (1.3.1)
jquery-rails (4.1.1)
image_optim_rails (0.4.0)
image_optim (~> 0.24.0)
rails
sprockets
image_size (1.5.0)
in_threads (1.4.0)
jquery-rails (4.3.1)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
thor (>= 0.14, < 2.0)
jshint (1.4.0)
jshint (1.5.0)
execjs (>= 1.4.0)
multi_json (~> 1.0)
therubyracer (~> 0.12.1)
json (1.8.3)
json (2.1.0)
jsonify (0.3.1)
multi_json (~> 1.0)
jsonify-rails (0.3.2)
actionpack
jsonify (< 0.4.0)
jwt (1.5.4)
kgio (2.10.0)
konacha (4.0.0)
actionpack (>= 4.1, < 5)
capybara
colorize
railties (>= 4.1, < 5)
sprockets (>= 2, < 4)
sprockets-rails (>= 2, < 4)
tilt
libv8 (3.16.14.15)
libxml-ruby (2.9.0)
jwt (1.5.6)
kgio (2.11.0)
libv8 (3.16.14.19)
libxml-ruby (3.0.0)
listen (3.1.5)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
ruby_dep (~> 1.2)
logstash-event (1.2.02)
logstasher (1.0.0)
activerecord (>= 4.0)
logstasher (1.2.1)
activesupport (>= 4.0)
logstash-event (~> 1.2.0)
request_store
loofah (2.0.3)
nokogiri (>= 1.5.9)
mail (2.6.4)
mail (2.6.6)
mime-types (>= 1.16, < 4)
method_source (0.8.2)
mime-types (3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521)
mimemagic (0.3.0)
mini_portile2 (2.1.0)
minitest (5.9.0)
mini_portile2 (2.2.0)
minitest (5.10.2)
multi_json (1.12.1)
multi_xml (0.5.5)
multi_xml (0.6.0)
multipart-post (2.0.0)
nokogiri (1.6.8)
mini_portile2 (~> 2.1.0)
pkg-config (~> 1.1.7)
nokogumbo (1.4.7)
nio4r (2.1.0)
nokogiri (1.8.0)
mini_portile2 (~> 2.2.0)
nokogumbo (1.4.13)
nokogiri
oauth (0.4.7)
oauth-plugin (0.5.1)
@ -160,147 +172,172 @@ GEM
oauth (~> 0.4.4)
oauth2 (>= 0.5.0)
rack
oauth2 (1.2.0)
faraday (>= 0.8, < 0.10)
oauth2 (1.4.0)
faraday (>= 0.8, < 0.13)
jwt (~> 1.0)
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (>= 1.2, < 3)
omniauth (1.3.1)
hashie (>= 1.2, < 4)
rack (>= 1.0, < 3)
omniauth-facebook (3.0.0)
omniauth (1.6.1)
hashie (>= 3.4.6, < 3.6.0)
rack (>= 1.6.2, < 3)
omniauth-facebook (4.0.0)
omniauth-oauth2 (~> 1.2)
omniauth-github (1.1.2)
omniauth (~> 1.0)
omniauth-oauth2 (~> 1.1)
omniauth-google-oauth2 (0.4.1)
jwt (~> 1.5.2)
omniauth-github (1.3.0)
omniauth (~> 1.5)
omniauth-oauth2 (>= 1.4.0, < 2.0)
omniauth-google-oauth2 (0.5.0)
jwt (~> 1.5)
multi_json (~> 1.3)
omniauth (>= 1.1.1)
omniauth-oauth2 (>= 1.3.1)
omniauth-mediawiki (0.0.3)
jwt (~> 1.0)
omniauth-oauth (~> 1.0)
omniauth-oauth (1.1.0)
oauth
omniauth (~> 1.0)
omniauth-oauth2 (1.4.0)
oauth2 (~> 1.0)
omniauth (~> 1.2)
omniauth-openid (1.0.1)
omniauth (~> 1.0)
rack-openid (~> 1.3.1)
omniauth-windowslive (0.0.9.1)
multi_json (>= 1.0.3)
omniauth-oauth2 (~> 1.0)
omniauth-windowslive (0.0.12)
multi_json (~> 1.12)
omniauth-oauth2 (~> 1.4)
paperclip (4.3.7)
activemodel (>= 3.2.0)
activesupport (>= 3.2.0)
cocaine (~> 0.5.5)
mime-types
mimemagic (= 0.3.0)
parser (2.3.1.2)
parallel (1.11.2)
parser (2.4.0.0)
ast (~> 2.2)
pg (0.18.4)
pkg-config (1.1.7)
poltergeist (1.10.0)
pg (0.21.0)
poltergeist (1.15.0)
capybara (~> 2.1)
cliver (~> 0.3.1)
websocket-driver (>= 0.2.0)
powerpack (0.1.1)
progress (3.1.1)
psych (2.1.0)
progress (3.3.1)
psych (2.2.4)
public_suffix (2.0.5)
r2 (0.2.6)
rack (1.6.4)
rack-cors (0.4.0)
rack (2.0.3)
rack-cors (0.4.1)
rack-openid (1.3.1)
rack (>= 1.1.0)
ruby-openid (>= 2.1.8)
rack-test (0.6.3)
rack (>= 1.0)
rack-uri_sanitizer (0.0.2)
rails (4.2.7)
actionmailer (= 4.2.7)
actionpack (= 4.2.7)
actionview (= 4.2.7)
activejob (= 4.2.7)
activemodel (= 4.2.7)
activerecord (= 4.2.7)
activesupport (= 4.2.7)
rails (5.0.4)
actioncable (= 5.0.4)
actionmailer (= 5.0.4)
actionpack (= 5.0.4)
actionview (= 5.0.4)
activejob (= 5.0.4)
activemodel (= 5.0.4)
activerecord (= 5.0.4)
activesupport (= 5.0.4)
bundler (>= 1.3.0, < 2.0)
railties (= 4.2.7)
sprockets-rails
rails-deprecated_sanitizer (1.0.3)
activesupport (>= 4.2.0.alpha)
rails-dom-testing (1.0.7)
activesupport (>= 4.2.0.beta, < 5.0)
nokogiri (~> 1.6.0)
rails-deprecated_sanitizer (>= 1.0.1)
railties (= 5.0.4)
sprockets-rails (>= 2.0.0)
rails-controller-testing (1.0.2)
actionpack (~> 5.x, >= 5.0.1)
actionview (~> 5.x, >= 5.0.1)
activesupport (~> 5.x)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
rails-html-sanitizer (1.0.3)
loofah (~> 2.0)
rails-i18n (4.0.9)
i18n (~> 0.7)
railties (~> 4.0)
railties (4.2.7)
actionpack (= 4.2.7)
activesupport (= 4.2.7)
rails-i18n (4.0.2)
i18n (~> 0.6)
rails (>= 4.0)
railties (5.0.4)
actionpack (= 5.0.4)
activesupport (= 5.0.4)
method_source
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rainbow (2.1.0)
rake (11.2.2)
redcarpet (3.3.4)
rainbow (2.2.2)
rake
rake (12.0.0)
rb-fsevent (0.9.8)
rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2)
record_tag_helper (1.0.0)
actionview (~> 5.x)
redcarpet (3.4.0)
ref (2.0.0)
request_store (1.3.1)
rinku (2.0.0)
rubocop (0.41.2)
parser (>= 2.3.1.1, < 3.0)
request_store (1.3.2)
rinku (2.0.2)
rotp (3.3.0)
rubocop (0.49.1)
parallel (~> 1.10)
parser (>= 2.3.3.1, < 3.0)
powerpack (~> 0.1)
rainbow (>= 1.99.1, < 3.0)
ruby-progressbar (~> 1.7)
unicode-display_width (~> 1.0, >= 1.0.1)
ruby-openid (2.7.0)
ruby-progressbar (1.8.1)
sanitize (4.0.1)
ruby_dep (1.5.0)
safe_yaml (1.0.4)
sanitize (4.5.0)
crass (~> 1.0.2)
nokogiri (>= 1.4.4)
nokogumbo (~> 1.4.1)
sass (3.4.22)
sass-rails (5.0.5)
sass (3.4.24)
sass-rails (5.0.6)
railties (>= 4.0.0, < 6)
sass (~> 3.1)
sprockets (>= 2.8, < 4.0)
sprockets-rails (>= 2.0, < 4.0)
tilt (>= 1.1, < 3)
simplecov (0.12.0)
secure_headers (3.6.5)
useragent
simplecov (0.14.1)
docile (~> 1.1.0)
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
simplecov-html (0.10.0)
soap4r-ruby1.9 (2.0.5)
sprockets (3.6.3)
simplecov-html (0.10.1)
sprockets (3.7.1)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
sprockets-rails (3.1.1)
sprockets-rails (3.2.0)
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
term-ansicolor (1.3.2)
term-ansicolor (1.6.0)
tins (~> 1.0)
therubyracer (0.12.2)
libv8 (~> 3.16.14.0)
therubyracer (0.12.3)
libv8 (~> 3.16.14.15)
ref
thor (0.19.1)
thread_safe (0.3.5)
tilt (2.0.5)
timecop (0.8.1)
tins (1.6.0)
tzinfo (1.2.2)
thor (0.19.4)
thread_safe (0.3.6)
tilt (2.0.7)
tins (1.14.0)
tzinfo (1.2.3)
thread_safe (~> 0.1)
uglifier (3.0.0)
uglifier (3.2.0)
execjs (>= 0.3.0, < 3)
unicode-display_width (1.1.0)
unicode-display_width (1.3.0)
useragent (0.16.8)
validates_email_format_of (1.6.3)
i18n
vendorer (0.1.16)
websocket-driver (0.6.4)
webmock (3.0.1)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff
websocket-driver (0.6.5)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.2)
xpath (2.0.0)
xpath (2.1.0)
nokogiri (~> 1.3)
PLATFORMS
@ -312,25 +349,27 @@ DEPENDENCIES
actionpack-page_caching
autoprefixer-rails
bigdecimal (~> 1.1.0)
coffee-rails (~> 4.1.0)
composite_primary_keys (~> 8.1.0)
canonical-rails
coffee-rails (~> 4.2)
composite_primary_keys (~> 9.0.7)
coveralls
dalli
deadlock_retry (>= 1.2.0)
dynamic_form
factory_girl_rails
faraday
geoip
htmlentities
http_accept_language (~> 2.0.0)
httpclient
i18n-js (>= 3.0.0.rc10)
image_optim (>= 0.22.0)
i18n-js (>= 3.0.0)
image_optim_rails
jquery-rails
jshint
json
jsonify-rails
kgio
konacha
libxml-ruby (>= 2.0.5)
listen
logstasher
minitest (~> 5.1)
oauth-plugin (>= 0.5.1)
@ -338,6 +377,7 @@ DEPENDENCIES
omniauth-facebook
omniauth-github
omniauth-google-oauth2 (>= 0.2.7)
omniauth-mediawiki (>= 0.0.3)
omniauth-openid
omniauth-windowslive
paperclip (~> 4.0)
@ -347,18 +387,21 @@ DEPENDENCIES
r2
rack-cors
rack-uri_sanitizer
rails (= 4.2.7)
rails (= 5.0.4)
rails-controller-testing
rails-i18n (~> 4.0.0)
record_tag_helper
redcarpet
rinku (>= 1.2.2)
rotp
rubocop
sanitize
sass-rails (~> 5.0)
soap4r-ruby1.9
timecop
secure_headers
uglifier (>= 1.3.0)
validates_email_format_of (>= 1.5.1)
vendorer
webmock
BUNDLED WITH
1.10.6
1.13.7

View file

@ -18,22 +18,22 @@ of packages required before you can get the various gems installed.
## Minimum requirements
* Ruby 2.0
* Ruby 2.3
* RubyGems 1.3.1+
* PostgreSQL 9.1+
* ImageMagick
* Bundler
* Javascript Runtime
These can be installed on Ubuntu 14.04 or later with:
These can be installed on Ubuntu 16.04 or later with:
```
sudo apt-get install ruby2.0 libruby2.0 ruby2.0-dev \
sudo apt-get install ruby2.3 libruby2.3 ruby2.3-dev \
libmagickwand-dev libxml2-dev libxslt1-dev nodejs \
apache2 apache2-threaded-dev build-essential git-core \
apache2 apache2-dev build-essential git-core \
postgresql postgresql-contrib libpq-dev postgresql-server-dev-all \
libsasl2-dev imagemagick
sudo gem2.0 install bundler
sudo gem2.3 install bundler
```
### Alternative platforms
@ -138,7 +138,7 @@ instructions below as appropriate.
### PostgreSQL account setup
We need to create a PostgreSQL role (i.e. user account) for your current user, and it needs to be a superuser so that we can create more database.
We need to create a PostgreSQL role (i.e. user account) for your current user, and it needs to be a superuser so that we can create more databases.
```
sudo -u postgres -i

View file

@ -1,6 +1,6 @@
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
require File.expand_path("../config/application", __FILE__)
require_relative "config/application"
OpenStreetMap::Application.load_tasks
Rails.application.load_tasks

View file

@ -6,10 +6,13 @@ On Ubuntu, it should be as simple as:
sudo apt-get install vagrant
```
Other Linux distributions should have similar installation instructions using `yum` or similar.
Other Linux distributions should have similar installation instructions using `dnf`, `pacman`, or similar.
Installers are available for Mac OS X and Windows, please see the [Vagrant project download page](http://www.vagrantup.com/downloads.html) for more information.
Note than until there are suitable _xenial64_ [vagrant boxes](https://atlas.hashicorp.com/boxes/search?utf8=%E2%9C%93&sort=&provider=&q=xenial64) for other providers,
the only virtualization provider supported is virtualbox. You might need to install it and specify `--provider virtualbox` when setting up your environment.
# Setting up openstreetmap-website
Once Vagrant has been installed, you can start an environment by checking out the openstreetmap-website code if you haven't already, then changing to the directory which contains the Vagrantfile by typing:

2
Vagrantfile vendored
View file

@ -4,7 +4,7 @@
Vagrant.configure("2") do |config|
# use official ubuntu image for virtualbox
config.vm.provider "virtualbox" do |vb, override|
override.vm.box = "ubuntu/trusty64"
override.vm.box = "ubuntu/xenial64"
override.vm.synced_folder ".", "/srv/openstreetmap-website"
vb.customize ["modifyvm", :id, "--memory", "1024"]
vb.customize ["modifyvm", :id, "--cpus", "2"]

View file

@ -11,13 +11,18 @@ folder 'vendor/assets' do
end
folder 'leaflet' do
file 'leaflet.js', 'http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet-src.js'
file 'leaflet.css', 'http://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.css'
file 'leaflet.js', 'https://unpkg.com/leaflet@1.1.0/dist/leaflet-src.js'
file 'leaflet.css', 'https://unpkg.com/leaflet@1.1.0/dist/leaflet.css'
[ 'layers.png', 'layers-2x.png',
'marker-icon.png', 'marker-icon-2x.png',
'marker-shadow.png' ].each do |image|
file "images/#{image}", "http://cdn.leafletjs.com/leaflet/v0.7.7/images/#{image}"
file "images/#{image}", "https://unpkg.com/leaflet@1.1.0/dist/images/#{image}"
end
from 'git://github.com/aratcliffe/Leaflet.contextmenu.git', :tag => 'v1.2.1' do
file 'leaflet.contextmenu.js', 'dist/leaflet.contextmenu.js'
file 'leaflet.contextmenu.css', 'dist/leaflet.contextmenu.css'
end
from 'git://github.com/kajic/leaflet-locationfilter.git' do
@ -26,7 +31,7 @@ folder 'vendor/assets' do
folder 'img', 'src/img'
end
from 'git://github.com/domoritz/leaflet-locatecontrol.git' do
from 'git://github.com/domoritz/leaflet-locatecontrol.git', :tag => 'v0.54.0' do
file 'leaflet.locate.js', 'src/L.Control.Locate.js'
end
@ -34,7 +39,7 @@ folder 'vendor/assets' do
file 'leaflet.osm.js', 'leaflet-osm.js'
end
from 'git://github.com/jieter/Leaflet.encoded.git' do
from 'git://github.com/jieter/Leaflet.encoded.git', :tag => '0.0.8' do
file 'leaflet.polyline.js', 'Polyline.encoded.js'
end
end
@ -49,7 +54,7 @@ folder 'vendor/assets' do
from 'git://github.com/openstreetmap/iD', :branch => 'release' do
folder 'iD/img', 'dist/img'
folder 'iD/locales', 'dist/locales'
folder 'iD/traffico', 'dist/traffico'
folder 'iD/mapillary-js', 'dist/mapillary-js'
file 'iD.css.erb', 'dist/iD.css' do |path|
rewrite(path) do |content|
@ -57,17 +62,7 @@ folder 'vendor/assets' do
end
end
file 'iD/traffico/stylesheets/traffico.css.erb', 'dist/traffico/stylesheets/traffico.css' do |path|
rewrite(path) do |content|
content.gsub(/url\("?\.\.\/([^#?")]+)([^"]*)"?\)/, 'url(<%= asset_path("iD/traffico/\1") %>\2)')
end
end
File.delete('vendor/assets/iD/iD/traffico/stylesheets/traffico.css')
file 'iD.js', 'dist/iD.js'
file 'presets.js', 'dist/presets.js'
file 'imagery.js', 'dist/imagery.js'
end
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Before After
Before After

View file

@ -115,4 +115,24 @@ $(document).ready(function () {
$("nav.primary li a").on("click", function() {
$("header").toggleClass("closed");
});
var application_data = $("head").data();
I18n.default_locale = OSM.DEFAULT_LOCALE;
I18n.locale = application_data.locale;
I18n.fallbacks = true;
OSM.preferred_editor = application_data.preferredEditor;
if (application_data.user) {
OSM.user = application_data.user;
if (application_data.userHome) {
OSM.home = application_data.userHome;
}
}
if (application_data.location) {
OSM.location = application_data.location;
}
});

View file

@ -0,0 +1,36 @@
$(document).ready(function () {
var id = $("#id-embed");
if (id.data("key")) {
var hashParams = OSM.params(location.hash.substring(1)),
mapParams = OSM.mapParams(),
params = {};
if (mapParams.object) {
params.id = mapParams.object.type[0] + mapParams.object.id;
mapParams = OSM.parseHash(location.hash);
if (mapParams.center) {
params.map = mapParams.zoom + '/' + mapParams.center.lat + '/' + mapParams.center.lng;
}
} else if (id.data("lat") && id.data("lon")) {
params.map = "16/" + id.data("lat") + "/" + id.data("lon");
} else {
params.map = (mapParams.zoom || 17) + '/' + mapParams.lat + '/' + mapParams.lon;
}
if (hashParams.background) params.background = hashParams.background;
if (hashParams.comment) params.comment = hashParams.comment;
if (hashParams.offset) params.offset = hashParams.offset;
if (hashParams.walkthrough) params.walkthrough = hashParams.walkthrough;
if (id.data("gpx")) {
params.gpx = id.data("gpx");
} else if (hashParams.gpx) {
params.gpx = hashParams.gpx;
}
id.attr("src", id.data("url") + "#" + querystring.stringify(params));
} else {
alert(I18n.t("site.edit.id_not_configured"));
}
});

View file

@ -0,0 +1,61 @@
//= require swfobject
$(document).ready(function () {
window.changesaved = true;
window.markChanged = function (saved) {
window.changesaved = saved;
}
$(window).on("beforeunload", function() {
if (!window.changesaved) {
return I18n.t("site.edit.potlatch_unsaved_changes");
}
});
window.updatelinks = function (lon, lat, zoom, layers, minlon, minlat, maxlon, maxlat, object) {
var hash = OSM.formatHash({ lon: lon, lat: lat, zoom: zoom });
if (hash !== location.hash) {
location.replace(hash);
}
updateLinks({ lon: lon, lat: lat }, zoom);
}
var potlatch = $("#potlatch"),
urlparams = OSM.params(),
potlatch_swf = <%= asset_path("potlatch/potlatch.swf").to_json %>,
install_swf = <%= asset_path("expressInstall.swf").to_json %>,
flashvars = {},
params = {},
attributes = {};
flashvars.winie = document.all && window.print ? true : false;
flashvars.token = potlatch.data("token");
if (potlatch.data("lat") && potlatch.data("lon")) {
flashvars.lat = potlatch.data("lat");
flashvars.long = potlatch.data("lon");
flashvars.scale = potlatch.data("zoom");
} else {
var mapParams = OSM.mapParams();
flashvars.lat = mapParams.lat;
flashvars.long = mapParams.lon;
flashvars.scale = mapParams.zoom || 17;
}
if (flashvars.scale < 11) flashvars.scale = 11;
if (urlparams.gpx) flashvars.gpx = urlparams.gpx;
if (urlparams.way) flashvars.way = urlparams.way;
if (urlparams.node) flashvars.node = urlparams.node;
if (urlparams.custombg) flashvars.custombg = urlparams.custombg;
attributes.id = "potlatch";
attributes.bgcolor = "#FFFFFF";
swfobject.embedSWF(potlatch_swf, "potlatch", "100%", "100%", "6",
install_swf, flashvars, params, attributes);
});

View file

@ -0,0 +1,83 @@
//= require swfobject
$(document).ready(function () {
window.changesaved = true;
window.markChanged = function (saved) {
window.changesaved = saved;
}
$(window).on("beforeunload", function() {
if (!window.changesaved) {
return I18n.t("site.edit.potlatch2_unsaved_changes");
}
});
window.mapMoved = $.throttle(250, function(lon, lat, zoom) {
var hash = OSM.formatHash({ lon: lon, lat: lat, zoom: zoom });
if (hash !== location.hash) {
location.replace(hash);
}
updateLinks({ lon: lon, lat: lat }, zoom);
});
var potlatch = $("#potlatch"),
urlparams = OSM.params(),
potlatch_swf = <%= asset_path("potlatch2.swf").to_json %>,
install_swf = <%= asset_path("expressInstall.swf").to_json %>,
flashvars = {},
params = {};
attributes = {};
if (potlatch.data("lat") && potlatch.data("lon")) {
flashvars.lat = potlatch.data("lat");
flashvars.lon = potlatch.data("lon");
flashvars.zoom = potlatch.data("zoom");
} else {
var mapParams = OSM.mapParams();
flashvars.lat = mapParams.lat;
flashvars.lon = mapParams.lon;
flashvars.zoom = mapParams.zoom || 17;
}
if (potlatch.data("token")) {
flashvars.oauth_token = potlatch.data("token");
flashvars.oauth_token_secret = potlatch.data("token-secret");
flashvars.oauth_consumer_key = potlatch.data("consumer-key");
flashvars.oauth_consumer_secret = potlatch.data("consumer-secret");
} else {
alert(I18n.t("site.edit.potlatch2_not_configured"));
}
flashvars.assets = <%= asset_path("potlatch2/assets.zip").to_json %>;
flashvars.font_library = <%= asset_path("potlatch2/FontLibrary.swf").to_json %>;
flashvars.locale = potlatch.data("locale");
flashvars.locale_paths = potlatch.data("locale") + "=" + potlatch.data("locale-path");
flashvars.intro_image = <%= asset_path("help/introduction.jpg").to_json %>;
flashvars.intro_video = <%= asset_path("help/introduction.mp4").to_json %>;
if (urlparams.gpx) flashvars.gpx = urlparams.gpx;
if (urlparams.tileurl) flashvars.tileurl = urlparams.tileurl;
flashvars.api = location.protocol + "//" + location.host + "/api/" + OSM.API_VERSION + "/";
flashvars.policy = location.protocol + "//" + location.host + "/api/crossdomain.xml";
flashvars.connection = "XML";
flashvars.show_help = "once";
flashvars.user_check = "warn";
flashvars.maximise_function = "maximiseMap";
flashvars.minimise_function = "minimiseMap";
flashvars.move_function = "mapMoved";
params.base = "/potlatch2";
attributes.id = "potlatch";
attributes.bgcolor = "#FFFFFF";
swfobject.embedSWF(potlatch_swf, "potlatch", "100%", "100%", "10.1.102",
install_swf, flashvars, params, attributes);
if (flashvars.lat && flashvars.lon) {
updateLinks({ lon: flashvars.lon, lat: flashvars.lat }, flashvars.scale);
}
});

View file

@ -18,6 +18,12 @@ window.onload = function () {
args[parts[0]] = decodeURIComponent(parts[1] || '');
}
var thunderforestOptions = {
<% if defined?(THUNDERFOREST_KEY) %>
apikey: <%= THUNDERFOREST_KEY.to_json %>
<% end %>
};
var map = L.map("map");
map.attributionControl.setPrefix('');
map.removeControl(map.attributionControl);
@ -25,9 +31,9 @@ window.onload = function () {
if (!args.layer || args.layer === "mapnik" || args.layer === "osmarender" || args.layer === "mapquest") {
new L.OSM.Mapnik().addTo(map);
} else if (args.layer === "cyclemap" || args.layer === "cycle map") {
new L.OSM.CycleMap().addTo(map);
new L.OSM.CycleMap(thunderforestOptions).addTo(map);
} else if (args.layer === "transportmap") {
new L.OSM.TransportMap().addTo(map);
new L.OSM.TransportMap(thunderforestOptions).addTo(map);
} else if (args.layer === "hot") {
new L.OSM.HOT().addTo(map);
}

View file

@ -1,3 +1,58 @@
//= require iD
//= require presets
//= require imagery
/* globals iD */
document.addEventListener("DOMContentLoaded", function() {
var container = document.getElementById("id-container");
if (typeof iD === 'undefined' || !iD.Detect().support) {
container.innerHTML = 'This editor is supported ' +
'in Firefox, Chrome, Safari, Opera, Edge, and Internet Explorer 11. ' +
'Please upgrade your browser or use Potlatch 2 to edit the map.';
container.className = 'unsupported';
} else {
var id = iD.Context()
.embed(true)
.assetPath("iD/")
.assetMap(JSON.parse(container.dataset.assetMap))
.locale(container.dataset.locale, container.dataset.localePath)
.preauth({
urlroot: location.protocol + "//" + location.host,
oauth_consumer_key: container.dataset.consumerKey,
oauth_secret: container.dataset.consumerSecret,
oauth_token: container.dataset.token,
oauth_token_secret: container.dataset.tokenSecret
});
id.map().on('move.embed', parent.$.throttle(250, function() {
if (id.inIntro()) return;
var zoom = ~~id.map().zoom(),
center = id.map().center(),
llz = { lon: center[0], lat: center[1], zoom: zoom };
parent.updateLinks(llz, zoom);
// Manually resolve URL to avoid iframe JS context weirdness.
// http://bl.ocks.org/jfirebaugh/5439412
var hash = parent.OSM.formatHash(llz);
if (hash !== parent.location.hash) {
parent.location.replace(parent.location.href.replace(/(#.*|$)/, hash));
}
}));
parent.$("body").on("click", "a.set_position", function (e) {
e.preventDefault();
var data = parent.$(this).data();
// 0ms timeout to avoid iframe JS context weirdness.
// http://bl.ocks.org/jfirebaugh/5439412
setTimeout(function() {
id.map().centerZoom(
[data.lon, data.lat],
Math.max(data.zoom || 15, 13));
}, 0);
});
id.ui()(container);
}
});

View file

@ -7,6 +7,8 @@
//= require leaflet.share
//= require leaflet.polyline
//= require leaflet.query
//= require leaflet.contextmenu
//= require index/contextmenu
//= require index/search
//= require index/browse
//= require index/export
@ -77,7 +79,8 @@ $(document).ready(function () {
var map = new L.OSM.Map("map", {
zoomControl: false,
layerControl: false
layerControl: false,
contextmenu: true
});
map.attributionControl.setPrefix('');
@ -95,14 +98,25 @@ $(document).ready(function () {
L.OSM.zoom({position: position})
.addTo(map);
L.control.locate({
var locate = L.control.locate({
position: position,
icon: 'icon geolocate',
iconLoading: 'icon geolocate',
strings: {
title: I18n.t('javascripts.map.locate.title'),
popup: I18n.t('javascripts.map.locate.popup')
}
}).addTo(map);
var locateContainer = locate.getContainer();
$(locateContainer)
.removeClass('leaflet-control-locate leaflet-bar')
.addClass('control-locate')
.children("a")
.removeClass('leaflet-bar-part leaflet-bar-part-single')
.addClass('control-button');
var sidebar = L.OSM.sidebar('#map-ui')
.addTo(map);
@ -136,6 +150,8 @@ $(document).ready(function () {
L.control.scale()
.addTo(map);
OSM.initializeContextMenu(map);
if (OSM.STATUS !== 'api_offline' && OSM.STATUS !== 'database_offline') {
OSM.initializeNotes(map);
if (params.layers.indexOf(map.noteLayer.options.code) >= 0) {
@ -146,6 +162,10 @@ $(document).ready(function () {
if (params.layers.indexOf(map.dataLayer.options.code) >= 0) {
map.addLayer(map.dataLayer);
}
if (params.layers.indexOf(map.gpsLayer.options.code) >= 0) {
map.addLayer(map.gpsLayer);
}
}
var placement = $('html').attr('dir') === 'rtl' ? 'right' : 'left';
@ -175,7 +195,7 @@ $(document).ready(function () {
});
var bannerExpiry = new Date();
expiry.setYear(expiry.getFullYear() + 1);
bannerExpiry.setYear(bannerExpiry.getFullYear() + 1);
$('#banner .close-wrap').on('click', function(e) {
var cookieId = e.target.id;

View file

@ -0,0 +1,85 @@
OSM.initializeContextMenu = function (map) {
map.contextmenu.addItem({
text: I18n.t("javascripts.context.directions_from"),
callback: function directionsFromHere(e) {
var precision = OSM.zoomPrecision(map.getZoom()),
latlng = e.latlng.wrap(),
lat = latlng.lat.toFixed(precision),
lng = latlng.lng.toFixed(precision);
OSM.router.route("/directions?" + querystring.stringify({
route: lat + "," + lng + ";" + $("#route_to").val()
}));
}
});
map.contextmenu.addItem({
text: I18n.t("javascripts.context.directions_to"),
callback: function directionsToHere(e) {
var precision = OSM.zoomPrecision(map.getZoom()),
latlng = e.latlng.wrap(),
lat = latlng.lat.toFixed(precision),
lng = latlng.lng.toFixed(precision);
OSM.router.route("/directions?" + querystring.stringify({
route: $("#route_from").val() + ";" + lat + "," + lng
}));
}
});
map.contextmenu.addItem({
text: I18n.t("javascripts.context.add_note"),
callback: function addNoteHere(e) {
var precision = OSM.zoomPrecision(map.getZoom()),
latlng = e.latlng.wrap(),
lat = latlng.lat.toFixed(precision),
lng = latlng.lng.toFixed(precision);
OSM.router.route("/note/new?lat=" + lat + "&lon=" + lng);
}
});
map.contextmenu.addItem({
text: I18n.t("javascripts.context.show_address"),
callback: function describeLocation(e) {
var precision = OSM.zoomPrecision(map.getZoom()),
latlng = e.latlng.wrap(),
lat = latlng.lat.toFixed(precision),
lng = latlng.lng.toFixed(precision);
OSM.router.route("/search?query=" + encodeURIComponent(lat + "," + lng));
}
});
map.contextmenu.addItem({
text: I18n.t("javascripts.context.query_features"),
callback: function queryFeatures(e) {
var precision = OSM.zoomPrecision(map.getZoom()),
latlng = e.latlng.wrap(),
lat = latlng.lat.toFixed(precision),
lng = latlng.lng.toFixed(precision);
OSM.router.route("/query?lat=" + lat + "&lon=" + lng);
}
});
map.contextmenu.addItem({
text: I18n.t("javascripts.context.centre_map"),
callback: function centreMap(e) {
map.panTo(e.latlng);
}
});
map.on("mousedown", function (e) {
if (e.originalEvent.shiftKey) map.contextmenu.disable();
else map.contextmenu.enable();
});
var updateMenu = function updateMenu () {
map.contextmenu.setDisabled(2, map.getZoom() < 12);
map.contextmenu.setDisabled(4, map.getZoom() < 14);
};
map.on("zoomend", updateMenu);
updateMenu();
};

View file

@ -26,6 +26,9 @@ OSM.Directions = function (map) {
Endpoint($("input[name='route_to']"), OSM.MARKER_RED)
];
var expiry = new Date();
expiry.setYear(expiry.getFullYear() + 10);
function Endpoint(input, iconUrl) {
var endpoint = {};
@ -207,8 +210,13 @@ OSM.Directions = function (map) {
'<span class="icon close"></span></a>' + I18n.t('javascripts.directions.directions') +
'</h2><p id="routing_summary">' +
I18n.t('javascripts.directions.distance') + ': ' + formatDistance(route.distance) + '. ' +
I18n.t('javascripts.directions.time') + ': ' + formatTime(route.time) + '.</p>' +
'<table id="turnbyturn" />';
I18n.t('javascripts.directions.time') + ': ' + formatTime(route.time) + '.';
if (typeof route.ascend !== 'undefined' && typeof route.descend !== 'undefined') {
html += '<br />' +
I18n.t('javascripts.directions.ascend') + ': ' + Math.round(route.ascend) + 'm. ' +
I18n.t('javascripts.directions.descend') + ': ' + Math.round(route.descend) +'m.';
}
html += '</p><table id="turnbyturn" />';
$('#sidebar_content')
.html(html);
@ -287,10 +295,15 @@ OSM.Directions = function (map) {
select.append("<option value='" + i + "'>" + I18n.t('javascripts.directions.engines.' + engine.id) + "</option>");
});
setEngine('osrm_car');
var chosenEngineId = $.cookie('_osm_directions_engine');
if(!chosenEngineId) {
chosenEngineId = 'osrm_car';
}
setEngine(chosenEngineId);
select.on("change", function (e) {
chosenEngine = engines[e.target.selectedIndex];
$.cookie('_osm_directions_engine', chosenEngine.id, { expires: expiry, path: '/' });
if (map.hasLayer(polyline)) {
getRoute();
}
@ -302,10 +315,14 @@ OSM.Directions = function (map) {
});
$(".routing_marker").on('dragstart', function (e) {
e.originalEvent.dataTransfer.effectAllowed = 'move';
e.originalEvent.dataTransfer.setData('type', $(this).data('type'));
var img = $("<img>").attr("src", $(e.originalEvent.target).attr("src"));
e.originalEvent.dataTransfer.setDragImage(img.get(0), 12, 21);
var dt = e.originalEvent.dataTransfer;
dt.effectAllowed = 'move';
var dragData = { type: $(this).data('type') };
dt.setData('text', JSON.stringify(dragData));
if (dt.setDragImage) {
var img = $("<img>").attr("src", $(e.originalEvent.target).attr("src"));
dt.setDragImage(img.get(0), 12, 21);
}
});
var page = {};
@ -321,7 +338,8 @@ OSM.Directions = function (map) {
$("#map").on('drop', function (e) {
e.preventDefault();
var oe = e.originalEvent;
var type = oe.dataTransfer.getData('type');
var dragData = JSON.parse(oe.dataTransfer.getData('text'));
var type = dragData.type;
var pt = L.DomEvent.getMousePosition(oe, map.getContainer()); // co-ordinates of the mouse pointer at present
pt.y += 20;
var ll = map.containerPointToLatLng(pt);

View file

@ -14,18 +14,19 @@ function GraphHopperEngine(id, vehicleType) {
return {
id: id,
creditline: '<a href="https://graphhopper.com/" target="_blank">Graphhopper</a>',
creditline: '<a href="https://www.graphhopper.com/" target="_blank">Graphhopper</a>',
draggable: false,
getRoute: function (points, callback) {
// GraphHopper Directions API documentation
// https://github.com/graphhopper/directions-api/blob/master/docs-routing.md
// https://graphhopper.com/api/1/docs/routing/
return $.ajax({
url: document.location.protocol + OSM.GRAPHHOPPER_URL,
data: {
vehicle: vehicleType,
locale: I18n.currentLocale(),
key: "LijBPDQGfu7Iiq80w3HzwB4RUDJbMbhs6BU0dEnn",
"ch.disable": vehicleType === "car",
type: "jsonp",
elevation: false,
instructions: true,
@ -49,12 +50,16 @@ function GraphHopperEngine(id, vehicleType) {
instrText += instr.text;
var latLng = line[instr.interval[0]];
var distInMeter = instr.distance;
var lineseg = [];
for (var j = instr.interval[0]; j <= instr.interval[1]; j++) {
lineseg.push({lat: line[j][0], lng: line[j][1]});
}
steps.push([
{lat: latLng.lat, lng: latLng.lng},
{lat: latLng[0], lng: latLng[1]},
instrCode,
instrText,
distInMeter,
[]
lineseg
]); // TODO does graphhopper map instructions onto line indices?
}
@ -62,7 +67,9 @@ function GraphHopperEngine(id, vehicleType) {
line: line,
steps: steps,
distance: path.distance,
time: path.time / 1000
time: path.time / 1000,
ascend: path.ascend,
descend: path.descend
});
},
error: function () {
@ -73,5 +80,6 @@ function GraphHopperEngine(id, vehicleType) {
};
}
OSM.Directions.addEngine(new GraphHopperEngine("graphhopper_car", "car"), true);
OSM.Directions.addEngine(new GraphHopperEngine("graphhopper_bicycle", "bike"), true);
OSM.Directions.addEngine(new GraphHopperEngine("graphhopper_foot", "foot"), true);

View file

@ -34,7 +34,7 @@ function MapzenEngine(id, costing) {
return {
id: id,
creditline: "<a href='https://mapzen.com/projects/valhalla' target='_blank'>Mapzen</a>",
creditline: "<a href='https://mapzen.com/products/turn-by-turn/' target='_blank'>Mapzen</a>",
draggable: false,
getRoute: function (points, callback) {

View file

@ -30,7 +30,6 @@ function OSRMEngine() {
'turn sharp left': 'javascripts.directions.instructions.sharp_left',
'turn left': 'javascripts.directions.instructions.turn_left',
'turn slight left': 'javascripts.directions.instructions.slight_left',
'trun straight': 'javascripts.directions.instructions.follow',
'roundabout': 'javascripts.directions.instructions.roundabout',
'rotary': 'javascripts.directions.instructions.roundabout',
'depart': 'javascripts.directions.instructions.start',
@ -56,7 +55,6 @@ function OSRMEngine() {
'turn slight left': 5,
'turn left': 6,
'turn sharp left': 7,
'trun straight': 0,
'roundabout': 10,
'rotary': 10,
'depart': 8,

View file

@ -69,7 +69,7 @@ OSM.NewNote = function(map) {
var marker = L.marker(feature.geometry.coordinates.reverse(), {
icon: noteIcons[feature.properties.status],
opacity: 0.9,
clickable: true
interactive: true
});
marker.id = feature.properties.id;
marker.addTo(noteLayer);
@ -77,7 +77,9 @@ OSM.NewNote = function(map) {
}
page.pushstate = page.popstate = function (path) {
OSM.loadSidebarContent(path, page.load);
OSM.loadSidebarContent(path, function () {
page.load(path);
});
};
function newHalo(loc, a) {
@ -97,7 +99,7 @@ OSM.NewNote = function(map) {
}
}
page.load = function () {
page.load = function (path) {
if (addNoteButton.hasClass("disabled")) return;
if (addNoteButton.hasClass("active")) return;
@ -105,12 +107,34 @@ OSM.NewNote = function(map) {
map.addLayer(noteLayer);
var mapSize = map.getSize();
var markerPosition;
var params = querystring.parse(path.substring(path.indexOf('?') + 1));
var markerLatlng;
markerPosition = [mapSize.x / 2, mapSize.y / 2];
if (params.lat && params.lon) {
markerLatlng = L.latLng(params.lat, params.lon);
newNote = L.marker(map.containerPointToLatLng(markerPosition), {
var markerPosition = map.latLngToContainerPoint(markerLatlng),
mapSize = map.getSize(),
panBy = L.point(0, 0);
if (markerPosition.x < 50) {
panBy.x = markerPosition.x - 50;
} else if (markerPosition.x > mapSize.x - 50) {
panBy.x = 50 - mapSize.x + markerPosition.x;
}
if (markerPosition.y < 50) {
panBy.y = markerPosition.y - 50;
} else if (markerPosition.y > mapSize.y - 50) {
panBy.y = 50 - mapSize.y + markerPosition.y;
}
map.panBy(panBy);
} else {
markerLatlng = map.getCenter();
}
newNote = L.marker(markerLatlng, {
icon: noteIcons["new"],
opacity: 0.9,
draggable: true

View file

@ -87,7 +87,7 @@ OSM.Note = function (map) {
currentNote = L.marker(latLng, {
icon: noteIcons[data.status],
opacity: 1,
clickable: true
interactive: true
});
map.addLayer(currentNote);

View file

@ -47,7 +47,7 @@ OSM.initializeNotes = function (map) {
icon: noteIcons[feature.properties.status],
title: feature.properties.comments[0].text,
opacity: 0.8,
clickable: true
interactive: true
});
marker.id = feature.properties.id;
marker.addTo(noteLayer);

View file

@ -12,7 +12,7 @@ OSM.Query = function(map) {
weight: 4,
opacity: 1,
fillOpacity: 0.5,
clickable: false
interactive: false
};
queryButton.on("click", function (e) {

View file

@ -50,7 +50,7 @@ L.OSM.layers = function(options) {
map.whenReady(function() {
var miniMap = L.map(div[0], {attributionControl: false, zoomControl: false})
.addLayer(new layer.constructor());
.addLayer(new layer.constructor({ apikey: layer.options.apikey }));
miniMap.dragging.disable();
miniMap.touchZoom.disable();
@ -176,6 +176,7 @@ L.OSM.layers = function(options) {
addOverlay(map.noteLayer, 'notes', OSM.MAX_NOTE_REQUEST_AREA);
addOverlay(map.dataLayer, 'data', OSM.MAX_REQUEST_AREA);
addOverlay(map.gpsLayer, 'gps', Number.POSITIVE_INFINITY);
}
options.sidebar.addPane($ui);

View file

@ -16,38 +16,51 @@ L.OSM.Map = L.Map.extend({
var copyright = I18n.t('javascripts.map.copyright', {copyright_url: '/copyright'});
var donate = I18n.t('javascripts.map.donate_link_text', {donate_url: 'http://donate.openstreetmap.org'});
this.baseLayers = [
new L.OSM.Mapnik({
attribution: copyright + " &hearts; " + donate,
code: "M",
keyid: "mapnik",
name: I18n.t("javascripts.map.base.standard")
}),
new L.OSM.CycleMap({
this.baseLayers = [];
this.baseLayers.push(new L.OSM.Mapnik({
attribution: copyright + " &hearts; " + donate,
code: "M",
keyid: "mapnik",
name: I18n.t("javascripts.map.base.standard")
}));
if (OSM.THUNDERFOREST_KEY) {
this.baseLayers.push(new L.OSM.CycleMap({
attribution: copyright + ". Tiles courtesy of <a href='http://www.thunderforest.com/' target='_blank'>Andy Allan</a>",
apikey: OSM.THUNDERFOREST_KEY,
code: "C",
keyid: "cyclemap",
name: I18n.t("javascripts.map.base.cycle_map")
}),
new L.OSM.TransportMap({
}));
this.baseLayers.push(new L.OSM.TransportMap({
attribution: copyright + ". Tiles courtesy of <a href='http://www.thunderforest.com/' target='_blank'>Andy Allan</a>",
apikey: OSM.THUNDERFOREST_KEY,
code: "T",
keyid: "transportmap",
name: I18n.t("javascripts.map.base.transport_map")
}),
new L.OSM.HOT({
attribution: copyright + ". Tiles courtesy of <a href='http://hot.openstreetmap.org/' target='_blank'>Humanitarian OpenStreetMap Team</a>",
code: "H",
keyid: "hot",
name: I18n.t("javascripts.map.base.hot")
})
];
}));
}
this.baseLayers.push(new L.OSM.HOT({
attribution: copyright + ". Tiles courtesy of <a href='http://hot.openstreetmap.org/' target='_blank'>Humanitarian OpenStreetMap Team</a>",
code: "H",
keyid: "hot",
name: I18n.t("javascripts.map.base.hot")
}));
this.noteLayer = new L.FeatureGroup();
this.noteLayer.options = {code: 'N'};
this.dataLayer = new L.OSM.DataLayer(null);
this.dataLayer.options.code = 'D';
this.gpsLayer = new L.OSM.GPS({
pane: "overlayPane",
code: "G",
name: I18n.t("javascripts.map.base.gps")
});
},
updateLayers: function(layerParam) {
@ -94,7 +107,7 @@ L.OSM.Map = L.Map.extend({
params.mlon = latLng.lng.toFixed(precision);
}
var url = 'http://' + OSM.SERVER_URL + '/',
var url = window.location.protocol + '//' + OSM.SERVER_URL + '/',
query = querystring.stringify(params),
hash = OSM.formatHash(this);
@ -108,7 +121,8 @@ L.OSM.Map = L.Map.extend({
var zoom = this.getZoom(),
latLng = marker && this.hasLayer(marker) ? marker.getLatLng().wrap() : this.getCenter().wrap(),
str = window.location.hostname.match(/^www\.openstreetmap\.org/i) ?
'http://osm.org/go/' : 'http://' + window.location.hostname + '/go/',
window.location.protocol + '//osm.org/go/' :
window.location.protocol + '//' + window.location.hostname + '/go/',
char_array = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_~",
x = Math.round((latLng.lng + 180.0) * ((1 << 30) / 90.0)),
y = Math.round((latLng.lat + 90.0) * ((1 << 30) / 45.0)),
@ -195,19 +209,18 @@ L.OSM.Map = L.Map.extend({
color: '#FF9500',
opacity: 1,
fillOpacity: 0,
clickable: false
interactive: false
};
this._object = object;
if (this._objectLoader) this._objectLoader.abort();
if (this._objectLayer) this.removeLayer(this._objectLayer);
this.removeObject();
var map = this;
this._objectLoader = $.ajax({
url: OSM.apiUrl(object),
dataType: "xml",
success: function (xml) {
map._object = object;
map._objectLayer = new L.OSM.DataLayer(null, {
styles: {
node: objectStyle,
@ -270,7 +283,7 @@ L.OSM.Map = L.Map.extend({
}
});
L.Icon.Default.imagePath = "/images";
L.Icon.Default.imagePath = "/images/";
L.Icon.Default.imageUrls = {
"/images/marker-icon.png": OSM.MARKER_ICON,

View file

@ -213,6 +213,15 @@ L.OSM.share = function (options) {
.attr('type', 'hidden')
.appendTo($form);
var csrf_param = $("meta[name=csrf-param]").attr("content"),
csrf_token = $("meta[name=csrf-token]").attr("content");
$('<input>')
.attr('name', csrf_param)
.attr('value', csrf_token)
.attr('type', 'hidden')
.appendTo($form);
$('<p>')
.attr('class', 'deemphasize')
.html(I18n.t('javascripts.share.image_size') + ' <span id="mapnik_image_width"></span> x <span id="mapnik_image_height"></span>')

View file

@ -1,18 +1,20 @@
//= require ohauth
$(document).ready(function () {
var application_data = $("head").data();
function makeAbsolute(url) {
var a = document.createElement('a');
a.href = url;
return a.href;
}
if (OSM.oauth_token) {
if (application_data.token) {
var headerGenerator = window.ohauth.headerGenerator({
consumer_key: OSM.oauth_consumer_key,
consumer_secret: OSM.oauth_consumer_secret,
token: OSM.oauth_token,
token_secret: OSM.oauth_token_secret
consumer_key: application_data.consumerKey,
consumer_secret: application_data.consumerSecret,
token: application_data.token,
token_secret: application_data.tokenSecret
});
$.ajaxPrefilter(function(options, jqxhr) {

View file

@ -16,6 +16,7 @@ OSM = {
MAPQUEST_DIRECTIONS_URL: <%= MAPQUEST_DIRECTIONS_URL.to_json %>,
MAPZEN_VALHALLA_URL: <%= MAPZEN_VALHALLA_URL.to_json %>,
OSRM_URL: <%= OSRM_URL.to_json %>,
DEFAULT_LOCALE: <%= I18n.default_locale.to_json %>,
<% if defined?(MAPQUEST_KEY) %>
MAPQUEST_KEY: <%= MAPQUEST_KEY.to_json %>,
@ -23,6 +24,9 @@ OSM = {
<% if defined?(MAPZEN_VALHALLA_KEY) %>
MAPZEN_VALHALLA_KEY: <%= MAPZEN_VALHALLA_KEY.to_json %>,
<% end %>
<% if defined?(THUNDERFOREST_KEY) %>
THUNDERFOREST_KEY: <%= THUNDERFOREST_KEY.to_json %>,
<% end %>
MARKER_GREEN: <%= image_path("marker-green.png").to_json %>,
MARKER_RED: <%= image_path("marker-red.png").to_json %>,
@ -35,6 +39,8 @@ OSM = {
OPEN_NOTE_MARKER: <%= image_path("open_note_marker.png").to_json %>,
CLOSED_NOTE_MARKER: <%= image_path("closed_note_marker.png").to_json %>,
SEARCHING: <%= image_path("searching.gif").to_json %>,
apiUrl: function (object) {
var url = "/api/" + OSM.API_VERSION + "/" + object.type + "/" + object.id;

View file

@ -12,14 +12,25 @@ $(document).ready(function () {
L.OSM.zoom({position: position})
.addTo(map);
L.control.locate({
var locate = L.control.locate({
position: position,
icon: 'icon geolocate',
iconLoading: 'icon geolocate',
strings: {
title: I18n.t('javascripts.map.locate.title'),
popup: I18n.t('javascripts.map.locate.popup')
}
}).addTo(map);
var locateContainer = locate.getContainer();
$(locateContainer)
.removeClass('leaflet-control-locate leaflet-bar')
.addClass('control-locate')
.children("a")
.removeClass('leaflet-bar-part leaflet-bar-part-single')
.addClass('control-button');
if (OSM.home) {
map.setView([OSM.home.lat, OSM.home.lon], 12);
} else {
@ -92,4 +103,20 @@ $(document).ready(function () {
} else {
enableAuth();
}
$("#user_all").change(function () {
$("#user_list input[type=checkbox]").prop("checked", $("#user_all").prop("checked"));
});
$("#content.user_confirm").each(function () {
$(this).hide();
$(this).find("#confirm").submit();
});
$("input[name=legale]").change(function () {
var url = $(this).data("url");
$("#contributorTerms").html("<img src='" + OSM.SEARCHING + "' />");
$("#contributorTerms").load(url);
});
});

View file

@ -7,7 +7,7 @@
<InputEncoding>UTF-8</InputEncoding>
<OutputEncoding>UTF-8</OutputEncoding>
<Image width="16" height="16">data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%10%00%00%00%10%08%06%00%00%00%1F%F3%FFa%00%00%00%19tEXtSoftware%00www.inkscape.org%9B%EE%3C%1A%00%00%01'IDATx%9C%9D%93%B1q%C30%0CE%1F%5Dd%80l%90I%C4*%A7%22%95%CF%85J%97%AE%B2%82%3DC%CE%03%A0%B3%9B%B8f%95%A3%17H%93%05%5C%A7%C8%0A%3F%05E%8A%92l%E7.%D0%E9N%02%81%07%E0Cr%FCaf%A6%FC%BC%5E%AF%DD%F4%3C%3Bt%C5%87%99)%84P%0E%DA%B6%BD%0AI%00%A1%A8%A8%1E%263S%D7u%C9'F%FE%9B%80%0C%C9%C9%22%BD'%B0%0A%AC%86%2CJ%DB%0E%22%11%8F%2F%D4%B3%22%8D%F34%CE%13u%06R%0C%40%D7u%AA%01%C5r%40%0Dq%88%C6%F9i%E8%7C%8CX%5D%A9M%95%D6%A3%A2Ti%C3Xx%CA%9C%F5mf3h%11%B6%07%B8%0APh%97%DD%1E%9E%5E%08!%D0%B6m%F1%87%108%1E%8EY5%007%03%5Cv%7B%00%3E%BF%3E%F8~x%1E%CD%B89l%00%F0I%0FWw%00%20%DB%AEJr%B6%E5%FB%09%80%C6y%CE%7D%91%1AP%B6p%2B%D9%BB%06%18V%3A%B5E%9F%AC%5B%95%AFY%3F%EE%20%A2mW%AA%93%DFN%3F%A0%E1%9B%F0u%E5%BC%BC%89%88%BC.%1F%D5'%DF%FD%C1%EE%F8%FFg%BFp%96%DF%E2%DCw%25%2B%00%00%00%00IEND%AEB%60%82</Image>
<Url type="text/html" method="get" template="http://www.openstreetmap.org/search">
<Url type="text/html" method="get" template="https://www.openstreetmap.org/search">
<Param name="query" value="{searchTerms}"/>
</Url>
<Query role="example" searchTerms="Reigate" />

View file

@ -148,6 +148,8 @@ small, aside {
.red { color: $red; }
.piwik { border: 0; }
/* Rules for icons */
.icon {
@ -491,7 +493,8 @@ body.compact {
background-color: black;
}
&.disabled {
&.disabled,
&.leaflet-disabled {
background-color: #333;
background-color: rgba(0,0,0,.5);
cursor: default;
@ -547,6 +550,10 @@ body.compact {
background: #fff;
font-size: 12px;
#sidebar_loader {
display: none;
}
> div {
position: relative;
float: left;
@ -582,12 +589,19 @@ body.compact {
.icon.close {
float: right;
cursor: pointer;
}
p.error {
background-color: #ff7070;
padding: 10px;
font-weight: bold;
.flash {
padding: 15px;
picture {
margin-right: -25px;
}
div.message {
margin-left: 30px;
}
}
}
@ -724,7 +738,7 @@ body.compact {
font-size: 16px;
text-stroke: 2px #fff;
background: rgba(255,255,255,.9);
z-index: 2; // For IE9
z-index: 1000;
input[type="radio"] {
display: none;
}
@ -869,10 +883,15 @@ body.compact {
#sidebar {
#sidebar_loader,
.search_more {
width: 100%;
margin: $lineheight auto;
}
.loader,
.load_more {
text-align: center;
margin: $lineheight auto;
margin: auto;
width: 40px;
display: block;
}
@ -1175,6 +1194,7 @@ tr.turn:hover {
width: 50%;
padding: 6px 10px;
word-wrap: break-word;
white-space: pre-wrap;
}
.browse-tag-k {
@ -1469,6 +1489,18 @@ tr.turn:hover {
}
}
/* Rules for the trace view */
.trace-view {
.trace_pending {
color: red;
}
.geo {
display: inline;
}
}
/* Rules for the new trace form */
#new_trace {
@ -1674,6 +1706,13 @@ tr.turn:hover {
float: left;
}
.diary-subscribe-buttons {
position:relative;
top: -30px;
left: 130px;
}
/* Rules for the log in page */
#login_auth_buttons {
@ -1694,6 +1733,14 @@ tr.turn:hover {
margin-bottom: $lineheight;
overflow: auto;
height: 20em;
li {
list-style: inherit;
}
ol ol {
list-style-type: lower-alpha;
}
}
#decline {
@ -1752,6 +1799,12 @@ tr.turn:hover {
border-radius: 0 2px 2px 0;
}
/* Rules for the oauth authorization page */
.oauth-authorize ul {
list-style: none;
}
/* Rules for messages pages */
.messages {

View file

@ -1,6 +1,7 @@
/*
*= require leaflet
*= require leaflet.locationfilter
*= require leaflet.contextmenu
*/
/* Override to serve images through the asset pipeline. */

View file

@ -133,7 +133,6 @@ body.small {
.leaflet-top.leaflet-right {
top: 10px !important;
z-index: 0;
}
.content_map {

View file

@ -46,7 +46,7 @@ class AmfController < ApplicationController
def amf_read
self.status = :ok
self.content_type = Mime::AMF
self.content_type = Mime[:amf]
self.response_body = Dispatcher.new(request.raw_post) do |message, *args|
logger.info("Executing AMF #{message}(#{args.join(',')})")
@ -74,7 +74,7 @@ class AmfController < ApplicationController
err = false # Abort batch on error
self.status = :ok
self.content_type = Mime::AMF
self.content_type = Mime[:amf]
self.response_body = Dispatcher.new(request.raw_post) do |message, *args|
logger.info("Executing AMF #{message}")
@ -86,14 +86,14 @@ class AmfController < ApplicationController
orn = renumberednodes.dup
result = putway(renumberednodes, *args)
result[4] = renumberednodes.reject { |k, _v| orn.key?(k) }
renumberedways[result[2]] = result[3] if result[0] == 0 && result[2] != result[3]
renumberedways[result[2]] = result[3] if result[0].zero? && result[2] != result[3]
when "putrelation" then
result = putrelation(renumberednodes, renumberedways, *args)
when "deleteway" then
result = deleteway(*args)
when "putpoi" then
result = putpoi(*args)
renumberednodes[result[2]] = result[3] if result[0] == 0 && result[2] != result[3]
renumberednodes[result[2]] = result[3] if result[0].zero? && result[2] != result[3]
when "startchangeset" then
result = startchangeset(*args)
end
@ -163,7 +163,7 @@ class AmfController < ApplicationController
end
# open a new changeset
if opennew != 0
if opennew.nonzero?
cs = Changeset.new
cs.tags = cstags
cs.user_id = user.id
@ -220,14 +220,14 @@ class AmfController < ApplicationController
loaded_lang = "en"
# Load English defaults
en = YAML.load(File.open("#{Rails.root}/config/potlatch/locales/en.yml"))["en"]
en = YAML.safe_load(File.open(Rails.root.join("config", "potlatch", "locales", "en.yml")))["en"]
if lang == "en"
return [loaded_lang, en]
else
# Use English as a fallback
begin
other = YAML.load(File.open("#{Rails.root}/config/potlatch/locales/#{lang}.yml"))[lang]
other = YAML.safe_load(File.open(Rails.root.join("config", "potlatch", "locales", "#{lang}.yml")))[lang]
loaded_lang = lang
rescue
other = en
@ -540,7 +540,7 @@ class AmfController < ApplicationController
tags = strip_non_xml_chars tags
relid = relid.to_i
visible = (visible.to_i != 0)
visible = visible.to_i.nonzero?
new_relation = nil
relation = nil
@ -644,7 +644,7 @@ class AmfController < ApplicationController
id = a[2].to_i
version = a[3].to_i
return -2, "Server error - node with id 0 found in way #{originalway}." if id == 0
return -2, "Server error - node with id 0 found in way #{originalway}." if id.zero?
return -2, "Server error - node with latitude -90 found in way #{originalway}." if lat == 90
id = renumberednodes[id] if renumberednodes[id]
@ -868,14 +868,14 @@ class AmfController < ApplicationController
def getuser(token) #:doc:
if token =~ /^(.+)\:(.+)$/
User.authenticate(:username => $1, :password => $2)
User.authenticate(:username => Regexp.last_match(1), :password => Regexp.last_match(2))
else
User.authenticate(:token => token)
end
end
def getlocales
@locales ||= Locale.list(Dir.glob("#{Rails.root}/config/potlatch/locales/*").collect { |f| File.basename(f, ".yml") })
@locales ||= Locale.list(Dir.glob(Rails.root.join("config", "potlatch", "locales", "*")).collect { |f| File.basename(f, ".yml") })
end
##
@ -914,7 +914,7 @@ class AmfController < ApplicationController
INNER JOIN current_ways ON current_ways.id =current_way_nodes.id
WHERE current_nodes.visible=TRUE
AND current_ways.visible=TRUE
AND #{OSM.sql_for_area(bbox, "current_nodes.")}
AND #{OSM.sql_for_area(bbox, 'current_nodes.')}
EOF
ActiveRecord::Base.connection.select_all(sql).collect { |a| [a["wayid"].to_i, a["version"].to_i] }
end
@ -927,7 +927,7 @@ class AmfController < ApplicationController
LEFT OUTER JOIN current_way_nodes cwn ON cwn.node_id=current_nodes.id
WHERE current_nodes.visible=TRUE
AND cwn.id IS NULL
AND #{OSM.sql_for_area(bbox, "current_nodes.")}
AND #{OSM.sql_for_area(bbox, 'current_nodes.')}
EOF
ActiveRecord::Base.connection.select_all(sql).each do |row|
poitags = {}
@ -947,7 +947,7 @@ class AmfController < ApplicationController
FROM current_relations cr
INNER JOIN current_relation_members crm ON crm.id=cr.id
INNER JOIN current_nodes cn ON crm.member_id=cn.id AND crm.member_type='Node'
WHERE #{OSM.sql_for_area(bbox, "cn.")}
WHERE #{OSM.sql_for_area(bbox, 'cn.')}
EOF
unless way_ids.empty?
sql += <<-EOF

View file

@ -100,7 +100,7 @@ class ApiController < ApplicationController
response.headers["Content-Disposition"] = "attachment; filename=\"tracks.gpx\""
render :text => doc.to_s, :content_type => "text/xml"
render :xml => doc.to_s
end
# This is probably the most common call of all. It is used for getting the
@ -198,7 +198,7 @@ class ApiController < ApplicationController
response.headers["Content-Disposition"] = "attachment; filename=\"map.osm\""
render :text => doc.to_s, :content_type => "text/xml"
render :xml => doc.to_s
end
# Get a list of the tiles that have changed within a specified time
@ -241,9 +241,9 @@ class ApiController < ApplicationController
doc.root << changes
render :text => doc.to_s, :content_type => "text/xml"
render :xml => doc.to_s
else
render :text => "Requested zoom is invalid, or the supplied start is after the end time, or the start duration is more than 24 hours", :status => :bad_request
render :plain => "Requested zoom is invalid, or the supplied start is after the end time, or the start duration is more than 24 hours", :status => :bad_request
end
end
@ -263,6 +263,9 @@ class ApiController < ApplicationController
area = XML::Node.new "area"
area["maximum"] = MAX_REQUEST_AREA.to_s
api << area
notearea = XML::Node.new "note_area"
notearea["maximum"] = MAX_NOTE_REQUEST_AREA.to_s
api << notearea
tracepoints = XML::Node.new "tracepoints"
tracepoints["per_page"] = TRACEPOINTS_PER_PAGE.to_s
api << tracepoints
@ -291,7 +294,7 @@ class ApiController < ApplicationController
policy << blacklist
doc.root << policy
render :text => doc.to_s, :content_type => "text/xml"
render :xml => doc.to_s
end
# External apps that use the api are able to query which permissions

View file

@ -1,7 +1,7 @@
class ApplicationController < ActionController::Base
include SessionPersistence
protect_from_forgery
protect_from_forgery :with => :exception
before_action :fetch_body
@ -41,7 +41,7 @@ class ApplicationController < ActionController::Base
if request.get?
redirect_to :controller => "user", :action => "login", :referer => request.fullpath
else
render :text => "", :status => :forbidden
head :forbidden
end
end
end
@ -61,8 +61,9 @@ class ApplicationController < ActionController::Base
# method, otherwise an OAuth token was used, which has to be checked.
unless current_token.nil?
unless current_token.read_attribute(cap)
report_error "OAuth token doesn't have that capability.", :forbidden
return false
set_locale
report_error t("oauth.permissions.missing"), :forbidden
false
end
end
end
@ -73,8 +74,8 @@ class ApplicationController < ActionController::Base
if request.cookies["_osm_session"].to_s == ""
if params[:cookie_test].nil?
session[:cookie_test] = true
redirect_to Hash[params].merge(:cookie_test => "true")
return false
redirect_to params.to_unsafe_h.merge(:cookie_test => "true")
false
else
flash.now[:warning] = t "application.require_cookies.cookies_needed"
end
@ -126,7 +127,7 @@ class ApplicationController < ActionController::Base
flash[:error] = t("application.require_moderator.not_a_moderator")
redirect_to :action => "index"
else
render :text => "", :status => :forbidden
head :forbidden
end
end
end
@ -152,9 +153,14 @@ class ApplicationController < ActionController::Base
# have we identified the user?
if @user
# check if the user has been banned
if @user.blocks.active.exists?
# NOTE: need slightly more helpful message than this.
report_error t("application.setup_user_auth.blocked"), :forbidden
user_block = @user.blocks.active.take
unless user_block.nil?
set_locale
if user_block.zero_hour?
report_error t("application.setup_user_auth.blocked_zero_hour"), :forbidden
else
report_error t("application.setup_user_auth.blocked"), :forbidden
end
end
# if the user hasn't seen the contributor terms then don't
@ -175,7 +181,7 @@ class ApplicationController < ActionController::Base
unless @user
# no auth, the user does not exist or the password was wrong
response.headers["WWW-Authenticate"] = "Basic realm=\"#{realm}\""
render :text => errormessage, :status => :unauthorized
render :plain => errormessage, :status => :unauthorized
return false
end
end
@ -191,8 +197,8 @@ class ApplicationController < ActionController::Base
def authorize_moderator(errormessage = "Access restricted to moderators")
# check user is a moderator
unless @user.moderator?
render :text => errormessage, :status => :forbidden
return false
render :plain => errormessage, :status => :forbidden
false
end
end
@ -220,14 +226,14 @@ class ApplicationController < ActionController::Base
def check_api_readable
if api_status == :offline
report_error "Database offline for maintenance", :service_unavailable
return false
false
end
end
def check_api_writable
unless api_status == :online
report_error "Database offline for maintenance", :service_unavailable
return false
false
end
end
@ -262,7 +268,7 @@ class ApplicationController < ActionController::Base
def require_public_data
unless @user.data_public?
report_error "You must make your edits public to upload new data", :forbidden
return false
false
end
end
@ -282,9 +288,9 @@ class ApplicationController < ActionController::Base
result.root << (XML::Node.new("status") << "#{Rack::Utils.status_code(status)} #{Rack::Utils::HTTP_STATUS_CODES[status]}")
result.root << (XML::Node.new("message") << message)
render :text => result.to_s, :content_type => "text/xml"
render :xml => result.to_s
else
render :text => message, :status => status, :content_type => "text/plain"
render :plain => message, :status => status
end
end
@ -315,7 +321,7 @@ class ApplicationController < ActionController::Base
def api_call_handle_error
yield
rescue ActiveRecord::RecordNotFound => ex
render :text => "", :status => :not_found
head :not_found
rescue LibXML::XML::Error, ArgumentError => ex
report_error ex.message, :bad_request
rescue ActiveRecord::RecordInvalid => ex
@ -343,7 +349,7 @@ class ApplicationController < ActionController::Base
##
# wrap an api call in a timeout
def api_call_timeout
OSM::Timer.timeout(API_TIMEOUT) do
OSM::Timer.timeout(API_TIMEOUT, Timeout::Error) do
yield
end
rescue Timeout::Error
@ -353,17 +359,14 @@ class ApplicationController < ActionController::Base
##
# wrap a web page in a timeout
def web_timeout
OSM::Timer.timeout(WEB_TIMEOUT) do
OSM::Timer.timeout(WEB_TIMEOUT, Timeout::Error) do
yield
end
rescue ActionView::Template::Error => ex
ex = ex.original_exception
if ex.is_a?(ActiveRecord::StatementInvalid) && ex.message =~ /execution expired/
ex = Timeout::Error.new
end
if ex.is_a?(Timeout::Error)
if ex.is_a?(Timeout::Error) ||
(ex.is_a?(ActiveRecord::StatementInvalid) && ex.message =~ /execution expired/)
render :action => "timeout"
else
raise
@ -375,7 +378,7 @@ class ApplicationController < ActionController::Base
##
# ensure that there is a "this_user" instance variable
def lookup_this_user
unless @this_user = User.active.find_by_display_name(params[:display_name])
unless @this_user = User.active.find_by(:display_name => params[:display_name])
render_unknown_user params[:display_name]
end
end
@ -388,7 +391,7 @@ class ApplicationController < ActionController::Base
respond_to do |format|
format.html { render :template => "user/no_such_user", :status => :not_found }
format.all { render :text => "", :status => :not_found }
format.all { head :not_found }
end
end
@ -406,6 +409,18 @@ class ApplicationController < ActionController::Base
end
def map_layout
append_content_security_policy_directives(
:connect_src => %w[nominatim.openstreetmap.org overpass-api.de router.project-osrm.org valhalla.mapzen.com],
:script_src => %w[graphhopper.com open.mapquestapi.com],
:img_src => %w[developer.mapquest.com]
)
if STATUS == :database_offline || STATUS == :api_offline
flash.now[:warning] = t("layouts.osm_offline")
elsif STATUS == :database_readonly || STATUS == :api_readonly
flash.now[:warning] = t("layouts.osm_read_only")
end
request.xhr? ? "xhr" : "map"
end
@ -423,6 +438,16 @@ class ApplicationController < ActionController::Base
helper_method :preferred_editor
def update_totp
if defined?(TOTP_KEY)
cookies["_osm_totp_token"] = {
:value => ROTP::TOTP.new(TOTP_KEY, :interval => 3600).now,
:domain => "openstreetmap.org",
:expires => 1.hour.from_now
}
end
end
private
# extract authorisation credentials from headers, returns user = nil if none
@ -452,6 +477,5 @@ class ApplicationController < ActionController::Base
end
# override to stop oauth plugin sending errors
def invalid_oauth_response
end
def invalid_oauth_response; end
end

View file

@ -9,7 +9,7 @@ class BrowseController < ApplicationController
def relation
@type = "relation"
@feature = Relation.find(params[:id])
@feature = Relation.preload(:relation_tags, :containing_relation_members, :changeset => [:changeset_tags, :user], :relation_members => :member).find(params[:id])
render "feature"
rescue ActiveRecord::RecordNotFound
render :action => "not_found", :status => :not_found
@ -17,7 +17,7 @@ class BrowseController < ApplicationController
def relation_history
@type = "relation"
@feature = Relation.find(params[:id])
@feature = Relation.preload(:relation_tags, :old_relations => [:old_tags, :changeset => [:changeset_tags, :user], :old_members => :member]).find(params[:id])
render "history"
rescue ActiveRecord::RecordNotFound
render :action => "not_found", :status => :not_found
@ -25,7 +25,7 @@ class BrowseController < ApplicationController
def way
@type = "way"
@feature = Way.preload(:way_tags, :containing_relation_members, :changeset => :user, :nodes => [:node_tags, :ways => :way_tags]).find(params[:id])
@feature = Way.preload(:way_tags, :containing_relation_members, :changeset => [:changeset_tags, :user], :nodes => [:node_tags, :ways => :way_tags]).find(params[:id])
render "feature"
rescue ActiveRecord::RecordNotFound
render :action => "not_found", :status => :not_found
@ -33,7 +33,7 @@ class BrowseController < ApplicationController
def way_history
@type = "way"
@feature = Way.preload(:way_tags, :old_ways => { :changeset => :user }).find(params[:id])
@feature = Way.preload(:way_tags, :old_ways => [:old_tags, :changeset => [:changeset_tags, :user], :old_nodes => { :node => [:node_tags, :ways] }]).find(params[:id])
render "history"
rescue ActiveRecord::RecordNotFound
render :action => "not_found", :status => :not_found
@ -41,7 +41,7 @@ class BrowseController < ApplicationController
def node
@type = "node"
@feature = Node.find(params[:id])
@feature = Node.preload(:node_tags, :containing_relation_members, :changeset => [:changeset_tags, :user], :ways => :way_tags).find(params[:id])
render "feature"
rescue ActiveRecord::RecordNotFound
render :action => "not_found", :status => :not_found
@ -49,7 +49,7 @@ class BrowseController < ApplicationController
def node_history
@type = "node"
@feature = Node.find(params[:id])
@feature = Node.preload(:node_tags, :old_nodes => [:old_tags, :changeset => [:changeset_tags, :user]]).find(params[:id])
render "history"
rescue ActiveRecord::RecordNotFound
render :action => "not_found", :status => :not_found

View file

@ -34,7 +34,7 @@ class ChangesetController < ApplicationController
# Subscribe user to changeset comments
cs.subscribers << @user
render :text => cs.id.to_s, :content_type => "text/plain"
render :plain => cs.id.to_s
end
##
@ -43,7 +43,7 @@ class ChangesetController < ApplicationController
def read
changeset = Changeset.find(params[:id])
render :text => changeset.to_xml(params[:include_discussion].presence).to_s, :content_type => "text/xml"
render :xml => changeset.to_xml(params[:include_discussion].presence).to_s
end
##
@ -61,7 +61,7 @@ class ChangesetController < ApplicationController
changeset.set_closed_time_now
changeset.save!
render :text => ""
head :ok
end
##
@ -83,7 +83,7 @@ class ChangesetController < ApplicationController
# the request is in pseudo-osm format... this is kind-of an
# abuse, maybe should change to some other format?
doc = XML::Parser.string(request.raw_post).parse
doc = XML::Parser.string(request.raw_post, :options => XML::Parser::Options::NOERROR).parse
doc.find("//osm/node").each do |n|
lon << n["lon"].to_f * GeoRecord::SCALE
lat << n["lat"].to_f * GeoRecord::SCALE
@ -104,7 +104,7 @@ class ChangesetController < ApplicationController
# save the larger bounding box and return the changeset, which
# will include the bigger bounding box.
cs.save!
render :text => cs.to_xml.to_s, :content_type => "text/xml"
render :xml => cs.to_xml.to_s
end
##
@ -132,7 +132,7 @@ class ChangesetController < ApplicationController
diff_reader = DiffReader.new(request.raw_post, changeset)
Changeset.transaction do
result = diff_reader.commit
render :text => result.to_s, :content_type => "text/xml"
render :xml => result.to_s
end
end
@ -197,7 +197,7 @@ class ChangesetController < ApplicationController
end
end
render :text => result.to_s, :content_type => "text/xml"
render :xml => result.to_s
end
##
@ -224,7 +224,7 @@ class ChangesetController < ApplicationController
results.root << cs.to_xml_node
end
render :text => results.to_s, :content_type => "text/xml"
render :xml => results.to_s
end
##
@ -244,52 +244,54 @@ class ChangesetController < ApplicationController
check_changeset_consistency(changeset, @user)
changeset.update_from(new_changeset, @user)
render :text => changeset.to_xml, :mime_type => "text/xml"
render :xml => changeset.to_xml.to_s
end
##
# list edits (open changesets) in reverse chronological order
# list non-empty changesets in reverse chronological order
def list
if request.format == :atom && params[:max_id]
redirect_to url_for(params.merge(:max_id => nil)), :status => :moved_permanently
@params = params.permit(:display_name, :bbox, :friends, :nearby, :max_id, :list)
if request.format == :atom && @params[:max_id]
redirect_to url_for(@params.merge(:max_id => nil)), :status => :moved_permanently
return
end
if params[:display_name]
user = User.find_by_display_name(params[:display_name])
if @params[:display_name]
user = User.find_by(:display_name => @params[:display_name])
if !user || !user.active?
render_unknown_user params[:display_name]
render_unknown_user @params[:display_name]
return
end
end
if (params[:friends] || params[:nearby]) && !@user
if (@params[:friends] || @params[:nearby]) && !@user
require_user
return
end
if request.format == :html && !params[:list]
if request.format == :html && !@params[:list]
require_oauth
render :action => :history, :layout => map_layout
else
changesets = conditions_nonempty(Changeset.all)
if params[:display_name]
if @params[:display_name]
changesets = if user.data_public? || user == @user
changesets.where(:user_id => user.id)
else
changesets.where("false")
end
elsif params[:bbox]
elsif @params[:bbox]
changesets = conditions_bbox(changesets, BoundingBox.from_bbox_params(params))
elsif params[:friends] && @user
elsif @params[:friends] && @user
changesets = changesets.where(:user_id => @user.friend_users.identifiable)
elsif params[:nearby] && @user
elsif @params[:nearby] && @user
changesets = changesets.where(:user_id => @user.nearby)
end
if params[:max_id]
changesets = changesets.where("changesets.id <= ?", params[:max_id])
if @params[:max_id]
changesets = changesets.where("changesets.id <= ?", @params[:max_id])
end
@edits = changesets.order("changesets.id DESC").limit(20).preload(:user, :changeset_tags, :comments)
@ -335,7 +337,7 @@ class ChangesetController < ApplicationController
changeset.subscribers << @user unless changeset.subscribers.exists?(@user.id)
# Return a copy of the updated changeset
render :text => changeset.to_xml.to_s, :content_type => "text/xml"
render :xml => changeset.to_xml.to_s
end
##
@ -356,7 +358,7 @@ class ChangesetController < ApplicationController
changeset.subscribers << @user
# Return a copy of the updated changeset
render :text => changeset.to_xml.to_s, :content_type => "text/xml"
render :xml => changeset.to_xml.to_s
end
##
@ -377,7 +379,7 @@ class ChangesetController < ApplicationController
changeset.subscribers.delete(@user)
# Return a copy of the updated changeset
render :text => changeset.to_xml.to_s, :content_type => "text/xml"
render :xml => changeset.to_xml.to_s
end
##
@ -396,7 +398,7 @@ class ChangesetController < ApplicationController
comment.update(:visible => false)
# Return a copy of the updated changeset
render :text => comment.changeset.to_xml.to_s, :content_type => "text/xml"
render :xml => comment.changeset.to_xml.to_s
end
##
@ -415,7 +417,7 @@ class ChangesetController < ApplicationController
comment.update(:visible => true)
# Return a copy of the updated changeset
render :text => comment.changeset.to_xml.to_s, :content_type => "text/xml"
render :xml => comment.changeset.to_xml.to_s
end
##
@ -440,7 +442,7 @@ class ChangesetController < ApplicationController
format.rss
end
rescue OSM::APIBadUserInput
render :text => "", :status => :bad_request
head :bad_request
end
private
@ -481,7 +483,7 @@ class ChangesetController < ApplicationController
raise OSM::APIBadUserInput.new("invalid user ID") if user.to_i < 1
u = User.find(user.to_i)
else
u = User.find_by_display_name(name)
u = User.find_by(:display_name => name)
end
# make sure we found a user
@ -535,10 +537,10 @@ class ChangesetController < ApplicationController
# if parameter 'open' is nill then open and closed changesets are returned
def conditions_open(changesets, open)
if open.nil?
return changesets
changesets
else
return changesets.where("closed_at >= ? and num_changes <= ?",
Time.now.getutc, Changeset::MAX_ELEMENTS)
changesets.where("closed_at >= ? and num_changes <= ?",
Time.now.getutc, Changeset::MAX_ELEMENTS)
end
end
@ -547,10 +549,10 @@ class ChangesetController < ApplicationController
# ('closed at' time has passed or changes limit is hit)
def conditions_closed(changesets, closed)
if closed.nil?
return changesets
changesets
else
return changesets.where("closed_at < ? or num_changes > ?",
Time.now.getutc, Changeset::MAX_ELEMENTS)
changesets.where("closed_at < ? or num_changes > ?",
Time.now.getutc, Changeset::MAX_ELEMENTS)
end
end
@ -559,12 +561,12 @@ class ChangesetController < ApplicationController
# (either specified as array or comma-separated string)
def conditions_ids(changesets, ids)
if ids.nil?
return changesets
changesets
elsif ids.empty?
raise OSM::APIBadUserInput.new("No changesets were given to search for")
else
ids = ids.split(",").collect(&:to_i)
return changesets.where(:id => ids)
changesets.where(:id => ids)
end
end

View file

@ -3,16 +3,16 @@ class DiaryEntryController < ApplicationController
before_action :authorize_web
before_action :set_locale
before_action :require_user, :only => [:new, :edit, :comment, :hide, :hidecomment]
before_action :require_user, :only => [:new, :edit, :comment, :hide, :hidecomment, :subscribe, :unsubscribe]
before_action :lookup_this_user, :only => [:view, :comments]
before_action :check_database_readable
before_action :check_database_writable, :only => [:new, :edit]
before_action :check_database_writable, :only => [:new, :edit, :comment, :hide, :hidecomment, :subscribe, :unsubscribe]
before_action :require_administrator, :only => [:hide, :hidecomment]
def new
@title = t "diary_entry.new.title"
if params[:diary_entry]
if request.post?
@diary_entry = DiaryEntry.new(entry_params)
@diary_entry.user = @user
@ -24,14 +24,18 @@ class DiaryEntryController < ApplicationController
else
@user.preferences.create(:k => "diary.default_language", :v => @diary_entry.language_code)
end
redirect_to :controller => "diary_entry", :action => "list", :display_name => @user.display_name
# Subscribe user to diary comments
@diary_entry.subscriptions.create(:user => @user)
redirect_to :action => "list", :display_name => @user.display_name
else
render :action => "edit"
end
else
default_lang = @user.preferences.where(:k => "diary.default_language").first
lang_code = default_lang ? default_lang.v : @user.preferred_language
@diary_entry = DiaryEntry.new(:language_code => lang_code)
@diary_entry = DiaryEntry.new(entry_params.merge(:language_code => lang_code))
set_map_location
render :action => "edit"
end
@ -42,9 +46,9 @@ class DiaryEntryController < ApplicationController
@diary_entry = DiaryEntry.find(params[:id])
if @user != @diary_entry.user
redirect_to :controller => "diary_entry", :action => "view", :id => params[:id]
redirect_to :action => "view", :id => params[:id]
elsif params[:diary_entry] && @diary_entry.update_attributes(entry_params)
redirect_to :controller => "diary_entry", :action => "view", :id => params[:id]
redirect_to :action => "view", :id => params[:id]
end
set_map_location
@ -57,11 +61,18 @@ class DiaryEntryController < ApplicationController
@diary_comment = @entry.comments.build(comment_params)
@diary_comment.user = @user
if @diary_comment.save
if @diary_comment.user != @entry.user
Notifier.diary_comment_notification(@diary_comment).deliver_now
# Notify current subscribers of the new comment
@entry.subscribers.visible.each do |user|
if @user != user
Notifier.diary_comment_notification(@diary_comment, user).deliver_now
end
end
redirect_to :controller => "diary_entry", :action => "view", :display_name => @entry.user.display_name, :id => @entry.id
# Add the commenter to the subscribers if necessary
@entry.subscriptions.create(:user => @user) unless @entry.subscribers.exists?(@user.id)
redirect_to :action => "view", :display_name => @entry.user.display_name, :id => @entry.id
else
render :action => "view"
end
@ -69,9 +80,29 @@ class DiaryEntryController < ApplicationController
render :action => "no_such_entry", :status => :not_found
end
def subscribe
diary_entry = DiaryEntry.find(params[:id])
diary_entry.subscriptions.create(:user => @user) unless diary_entry.subscribers.exists?(@user.id)
redirect_to :action => "view", :display_name => diary_entry.user.display_name, :id => diary_entry.id
rescue ActiveRecord::RecordNotFound
render :action => "no_such_entry", :status => :not_found
end
def unsubscribe
diary_entry = DiaryEntry.find(params[:id])
diary_entry.subscriptions.where(:user => @user).delete_all if diary_entry.subscribers.exists?(@user.id)
redirect_to :action => "view", :display_name => diary_entry.user.display_name, :id => diary_entry.id
rescue ActiveRecord::RecordNotFound
render :action => "no_such_entry", :status => :not_found
end
def list
if params[:display_name]
@this_user = User.active.find_by_display_name(params[:display_name])
@this_user = User.active.find_by(:display_name => params[:display_name])
if @this_user
@title = t "diary_entry.list.user_title", :user => @this_user.display_name
@ -97,7 +128,7 @@ class DiaryEntryController < ApplicationController
return
end
else
@entries = DiaryEntry.joins(:user).where(:users => { :status => %w(active confirmed) })
@entries = DiaryEntry.joins(:user).where(:users => { :status => %w[active confirmed] })
if params[:language]
@title = t "diary_entry.list.in_language_title", :language => Language.find(params[:language]).english_name
@ -107,6 +138,8 @@ class DiaryEntryController < ApplicationController
end
end
@params = params.permit(:display_name, :friends, :nearby, :language)
@page = (params[:page] || 1).to_i
@page_size = 20
@ -119,7 +152,7 @@ class DiaryEntryController < ApplicationController
def rss
if params[:display_name]
user = User.active.find_by_display_name(params[:display_name])
user = User.active.find_by(:display_name => params[:display_name])
if user
@entries = user.diary_entries
@ -127,11 +160,11 @@ class DiaryEntryController < ApplicationController
@description = I18n.t("diary_entry.feed.user.description", :user => user.display_name)
@link = "http://#{SERVER_URL}/user/#{user.display_name}/diary"
else
render :text => "", :status => :not_found
head :not_found
return
end
else
@entries = DiaryEntry.joins(:user).where(:users => { :status => %w(active confirmed) })
@entries = DiaryEntry.joins(:user).where(:users => { :status => %w[active confirmed] })
if params[:language]
@entries = @entries.where(:language_code => params[:language])
@ -190,6 +223,8 @@ class DiaryEntryController < ApplicationController
# return permitted diary entry parameters
def entry_params
params.require(:diary_entry).permit(:title, :body, :language_code, :latitude, :longitude)
rescue ActionController::ParameterMissing
ActionController::Parameters.new.permit(:title, :body, :language_code, :latitude, :longitude)
end
##
@ -204,7 +239,7 @@ class DiaryEntryController < ApplicationController
def require_administrator
unless @user.administrator?
flash[:error] = t("user.filter.not_an_administrator")
redirect_to :controller => "diary_entry", :action => "view"
redirect_to :action => "view"
end
end

View file

@ -1,6 +1,7 @@
class ExportController < ApplicationController
before_action :authorize_web
before_action :set_locale
before_action :update_totp, :only => [:finish]
caches_page :embed
@ -11,7 +12,7 @@ class ExportController < ApplicationController
if format == "osm"
# redirect to API map get
redirect_to "http://api.openstreetmap.org/api/#{API_VERSION}/map?bbox=#{bbox}"
redirect_to :controller => "api", :action => "map", :bbox => bbox
elsif format == "mapnik"
# redirect to a special 'export' cgi script
@ -22,6 +23,5 @@ class ExportController < ApplicationController
end
end
def embed
end
def embed; end
end

View file

@ -10,22 +10,21 @@ class GeocoderController < ApplicationController
before_action :require_oauth, :only => [:search]
def search
normalize_params
@params = normalize_params
@sources = []
if params[:lat] && params[:lon]
if @params[:lat] && @params[:lon]
@sources.push "latlon"
@sources.push "osm_nominatim_reverse"
@sources.push "geonames_reverse" if defined?(GEONAMES_USERNAME)
elsif params[:query]
if params[:query] =~ /^\d{5}(-\d{4})?$/
elsif @params[:query]
if @params[:query] =~ /^\d{5}(-\d{4})?$/
@sources.push "us_postcode"
@sources.push "osm_nominatim"
elsif params[:query] =~ /^(GIR 0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]|[A-HK-Y][0-9]([0-9]|[ABEHMNPRV-Y]))|[0-9][A-HJKS-UW])\s*[0-9][ABD-HJLNP-UW-Z]{2})$/i
elsif @params[:query] =~ /^(GIR 0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HK-Y][0-9]|[A-HK-Y][0-9]([0-9]|[ABEHMNPRV-Y]))|[0-9][A-HJKS-UW])\s*[0-9][ABD-HJLNP-UW-Z]{2})$/i
@sources.push "uk_postcode"
@sources.push "osm_nominatim"
elsif params[:query] =~ /^[A-Z]\d[A-Z]\s*\d[A-Z]\d$/i
elsif @params[:query] =~ /^[A-Z]\d[A-Z]\s*\d[A-Z]\d$/i
@sources.push "ca_postcode"
@sources.push "osm_nominatim"
else
@ -35,7 +34,7 @@ class GeocoderController < ApplicationController
end
if @sources.empty?
render :text => "", :status => :bad_request
head :bad_request
else
render :layout => map_layout
end
@ -149,7 +148,7 @@ class GeocoderController < ApplicationController
exclude = "&exclude_place_ids=#{params[:exclude]}" if params[:exclude]
# ask nominatim
response = fetch_xml("http:#{NOMINATIM_URL}search?format=xml&q=#{escape_query(query)}#{viewbox}#{exclude}&accept-language=#{http_accept_language.user_preferred_languages.join(',')}")
response = fetch_xml("http:#{NOMINATIM_URL}search?format=xml&extratags=1&q=#{escape_query(query)}#{viewbox}#{exclude}&accept-language=#{http_accept_language.user_preferred_languages.join(',')}")
# extract the results from the response
results = response.elements["searchresults"]
@ -161,7 +160,9 @@ class GeocoderController < ApplicationController
@results = []
# create parameter hash for "more results" link
@more_params = params.merge(:exclude => more_url_params["exclude_place_ids"].first)
@more_params = params
.permit(:query, :minlon, :minlat, :maxlon, :maxlat, :exclude)
.merge(:exclude => more_url_params["exclude_place_ids"].first)
# parse the response
results.elements.each("place") do |place|
@ -179,6 +180,11 @@ class GeocoderController < ApplicationController
if klass == "boundary" && type == "administrative"
rank = (place.attributes["place_rank"].to_i + 1) / 2
prefix_name = t "geocoder.search_osm_nominatim.admin_levels.level#{rank}", :default => prefix_name
place.elements["extratags"].elements.each("tag") do |extratag|
if extratag.attributes["key"] == "place"
prefix_name = t "geocoder.search_osm_nominatim.prefix.place.#{extratag.attributes['value']}", :default => prefix_name
end
end
end
prefix = t "geocoder.search_osm_nominatim.prefix_format", :name => prefix_name
object_type = place.attributes["osm_type"]
@ -311,29 +317,30 @@ class GeocoderController < ApplicationController
end
def normalize_params
query = params[:query]
return unless query
if query = params[:query]
query.strip!
query.strip!
if latlon = query.match(/^([NS])\s*(\d{1,3}(\.\d*)?)\W*([EW])\s*(\d{1,3}(\.\d*)?)$/).try(:captures) # [NSEW] decimal degrees
params.merge!(nsew_to_decdeg(latlon)).delete(:query)
elsif latlon = query.match(/^(\d{1,3}(\.\d*)?)\s*([NS])\W*(\d{1,3}(\.\d*)?)\s*([EW])$/).try(:captures) # decimal degrees [NSEW]
params.merge!(nsew_to_decdeg(latlon)).delete(:query)
if latlon = query.match(/^([NS])\s*(\d{1,3}(\.\d*)?)\W*([EW])\s*(\d{1,3}(\.\d*)?)$/).try(:captures) # [NSEW] decimal degrees
params.merge!(nsew_to_decdeg(latlon)).delete(:query)
elsif latlon = query.match(/^(\d{1,3}(\.\d*)?)\s*([NS])\W*(\d{1,3}(\.\d*)?)\s*([EW])$/).try(:captures) # decimal degrees [NSEW]
params.merge!(nsew_to_decdeg(latlon)).delete(:query)
elsif latlon = query.match(/^([NS])\s*(\d{1,3})°?\s*(\d{1,3}(\.\d*)?)?[']?\W*([EW])\s*(\d{1,3})°?\s*(\d{1,3}(\.\d*)?)?[']?$/).try(:captures) # [NSEW] degrees, decimal minutes
params.merge!(ddm_to_decdeg(latlon)).delete(:query)
elsif latlon = query.match(/^(\d{1,3})°?\s*(\d{1,3}(\.\d*)?)?[']?\s*([NS])\W*(\d{1,3})°?\s*(\d{1,3}(\.\d*)?)?[']?\s*([EW])$/).try(:captures) # degrees, decimal minutes [NSEW]
params.merge!(ddm_to_decdeg(latlon)).delete(:query)
elsif latlon = query.match(/^([NS])\s*(\d{1,3})°?\s*(\d{1,3}(\.\d*)?)?[']?\W*([EW])\s*(\d{1,3})°?\s*(\d{1,3}(\.\d*)?)?[']?$/).try(:captures) # [NSEW] degrees, decimal minutes
params.merge!(ddm_to_decdeg(latlon)).delete(:query)
elsif latlon = query.match(/^(\d{1,3})°?\s*(\d{1,3}(\.\d*)?)?[']?\s*([NS])\W*(\d{1,3})°?\s*(\d{1,3}(\.\d*)?)?[']?\s*([EW])$/).try(:captures) # degrees, decimal minutes [NSEW]
params.merge!(ddm_to_decdeg(latlon)).delete(:query)
elsif latlon = query.match(/^([NS])\s*(\d{1,3})°?\s*(\d{1,2})[']?\s*(\d{1,3}(\.\d*)?)?["″]?\W*([EW])\s*(\d{1,3})°?\s*(\d{1,2})[']?\s*(\d{1,3}(\.\d*)?)?["″]?$/).try(:captures) # [NSEW] degrees, minutes, decimal seconds
params.merge!(dms_to_decdeg(latlon)).delete(:query)
elsif latlon = query.match(/^(\d{1,3})°?\s*(\d{1,2})[']?\s*(\d{1,3}(\.\d*)?)?["″]\s*([NS])\W*(\d{1,3})°?\s*(\d{1,2})[']?\s*(\d{1,3}(\.\d*)?)?["″]?\s*([EW])$/).try(:captures) # degrees, minutes, decimal seconds [NSEW]
params.merge!(dms_to_decdeg(latlon)).delete(:query)
elsif latlon = query.match(/^([NS])\s*(\d{1,3})°?\s*(\d{1,2})[']?\s*(\d{1,3}(\.\d*)?)?["″]?\W*([EW])\s*(\d{1,3})°?\s*(\d{1,2})[']?\s*(\d{1,3}(\.\d*)?)?["″]?$/).try(:captures) # [NSEW] degrees, minutes, decimal seconds
params.merge!(dms_to_decdeg(latlon)).delete(:query)
elsif latlon = query.match(/^(\d{1,3})°?\s*(\d{1,2})[']?\s*(\d{1,3}(\.\d*)?)?["″]\s*([NS])\W*(\d{1,3})°?\s*(\d{1,2})[']?\s*(\d{1,3}(\.\d*)?)?["″]?\s*([EW])$/).try(:captures) # degrees, minutes, decimal seconds [NSEW]
params.merge!(dms_to_decdeg(latlon)).delete(:query)
elsif latlon = query.match(/^\s*([+-]?\d+(\.\d*)?)\s*[\s,]\s*([+-]?\d+(\.\d*)?)\s*$/)
params.merge!(:lat => latlon[1].to_f, :lon => latlon[3].to_f).delete(:query)
elsif latlon = query.match(/^\s*([+-]?\d+(\.\d*)?)\s*[\s,]\s*([+-]?\d+(\.\d*)?)\s*$/)
params.merge!(:lat => latlon[1].to_f, :lon => latlon[3].to_f).delete(:query)
end
end
params.permit(:query, :lat, :lon, :zoom, :minlat, :minlon, :maxlat, :maxlon)
end
def nsew_to_decdeg(captures)

View file

@ -13,7 +13,7 @@ class MessageController < ApplicationController
# clicks send.
# The display_name param is the display name of the user that the message is being sent to.
def new
if params[:message]
if request.post?
if @user.sent_messages.where("sent_on >= ?", Time.now.getutc - 1.hour).count >= MAX_MESSAGES_PER_HOUR
flash[:error] = t "message.new.limit_exceeded"
else
@ -25,12 +25,12 @@ class MessageController < ApplicationController
if @message.save
flash[:notice] = t "message.new.message_sent"
Notifier.message_notification(@message).deliver_now
redirect_to :controller => "message", :action => "inbox", :display_name => @user.display_name
redirect_to :action => "inbox", :display_name => @user.display_name
end
end
end
@message ||= Message.new(:recipient => @this_user)
@message ||= Message.new(message_params.merge(:recipient => @this_user))
@title = t "message.new.title"
end
@ -39,7 +39,7 @@ class MessageController < ApplicationController
message = Message.find(params[:message_id])
if message.to_user_id == @user.id
message.update_attribute(:message_read, true)
message.update(:message_read => true)
@message = Message.new(
:recipient => message.sender,
@ -81,7 +81,7 @@ class MessageController < ApplicationController
@title = t "message.inbox.title"
if @user && params[:display_name] == @user.display_name
else
redirect_to :controller => "message", :action => "inbox", :display_name => @user.display_name
redirect_to :action => "inbox", :display_name => @user.display_name
end
end
@ -90,7 +90,7 @@ class MessageController < ApplicationController
@title = t "message.outbox.title"
if @user && params[:display_name] == @user.display_name
else
redirect_to :controller => "message", :action => "outbox", :display_name => @user.display_name
redirect_to :action => "outbox", :display_name => @user.display_name
end
end
@ -107,7 +107,7 @@ class MessageController < ApplicationController
@message.message_read = message_read
if @message.save && !request.xhr?
flash[:notice] = notice
redirect_to :controller => "message", :action => "inbox", :display_name => @user.display_name
redirect_to :action => "inbox", :display_name => @user.display_name
end
rescue ActiveRecord::RecordNotFound
@title = t "message.no_such_message.title"
@ -125,7 +125,7 @@ class MessageController < ApplicationController
if params[:referer]
redirect_to params[:referer]
else
redirect_to :controller => "message", :action => "inbox", :display_name => @user.display_name
redirect_to :action => "inbox", :display_name => @user.display_name
end
end
rescue ActiveRecord::RecordNotFound
@ -139,5 +139,7 @@ class MessageController < ApplicationController
# return permitted message parameters
def message_params
params.require(:message).permit(:title, :body)
rescue ActionController::ParameterMissing
ActionController::Parameters.new.permit(:title, :body)
end
end

View file

@ -19,7 +19,7 @@ class NodeController < ApplicationController
# Assume that Node.from_xml has thrown an exception if there is an error parsing the xml
node.create_with_history @user
render :text => node.id.to_s, :content_type => "text/plain"
render :plain => node.id.to_s
end
# Dump the details on a node given in params[:id]
@ -29,9 +29,9 @@ class NodeController < ApplicationController
response.last_modified = node.timestamp
if node.visible
render :text => node.to_xml.to_s, :content_type => "text/xml"
render :xml => node.to_xml.to_s
else
render :text => "", :status => :gone
head :gone
end
end
@ -45,7 +45,7 @@ class NodeController < ApplicationController
end
node.update_from(new_node, @user)
render :text => node.version.to_s, :content_type => "text/plain"
render :plain => node.version.to_s
end
# Delete a node. Doesn't actually delete it, but retains its history
@ -59,7 +59,7 @@ class NodeController < ApplicationController
raise OSM::APIBadUserInput.new("The id in the url (#{node.id}) is not the same as provided in the xml (#{new_node.id})")
end
node.delete_with_history!(new_node, @user)
render :text => node.version.to_s, :content_type => "text/plain"
render :plain => node.version.to_s
end
# Dump the details on many nodes whose ids are given in the "nodes" parameter.
@ -79,6 +79,6 @@ class NodeController < ApplicationController
doc.root << node.to_xml_node
end
render :text => doc.to_s, :content_type => "text/xml"
render :xml => doc.to_s
end
end

View file

@ -1,6 +1,7 @@
class NotesController < ApplicationController
layout "site", :only => [:mine]
skip_before_action :verify_authenticity_token, :except => [:mine]
before_action :check_api_readable
before_action :authorize_web, :only => [:mine]
before_action :setup_user_auth, :only => [:create, :comment]
@ -127,7 +128,7 @@ class NotesController < ApplicationController
comment = params[:text]
# Find the note and check it is valid
@note = Note.find_by_id(id)
@note = Note.find_by(:id => id)
raise OSM::APINotFoundError unless @note
raise OSM::APIAlreadyDeletedError.new("note", @note.id) unless @note.visible?
raise OSM::APINoteAlreadyClosedError.new(@note) if @note.closed?
@ -157,7 +158,7 @@ class NotesController < ApplicationController
comment = params[:text]
# Find the note and check it is valid
@note = Note.find_by_id(id)
@note = Note.find_by(:id => id)
raise OSM::APINotFoundError unless @note
raise OSM::APIAlreadyDeletedError.new("note", @note.id) unless @note.visible? || @user.moderator?
raise OSM::APINoteAlreadyOpenError.new(@note) unless @note.closed? || !@note.visible?
@ -277,7 +278,8 @@ class NotesController < ApplicationController
# Display a list of notes by a specified user
def mine
if params[:display_name]
if @this_user = User.active.find_by_display_name(params[:display_name])
if @this_user = User.active.find_by(:display_name => params[:display_name])
@params = params.permit(:display_name)
@title = t "note.mine.title", :user => @this_user.display_name
@heading = t "note.mine.heading", :user => @this_user.display_name
@description = t "note.mine.subheading", :user => render_to_string(:partial => "user", :object => @this_user)
@ -285,7 +287,7 @@ class NotesController < ApplicationController
@page_size = 10
@notes = @this_user.notes
@notes = @notes.visible unless @user && @user.moderator?
@notes = @notes.order("updated_at DESC, id").uniq.offset((@page - 1) * @page_size).limit(@page_size).preload(:comments => :author).to_a
@notes = @notes.order("updated_at DESC, id").distinct.offset((@page - 1) * @page_size).limit(@page_size).preload(:comments => :author).to_a
else
@title = t "user.no_such_user.title"
@not_found_user = params[:display_name]
@ -316,7 +318,7 @@ class NotesController < ApplicationController
end
##
# Generate a condition to choose which bugs we want based
# Generate a condition to choose which notes we want based
# on their status and the user's request parameters
def closed_condition(notes)
closed_since = if params[:closed]
@ -345,7 +347,7 @@ class NotesController < ApplicationController
attributes[:author_ip] = request.remote_ip
end
comment = note.comments.create(attributes)
comment = note.comments.create!(attributes)
note.comments.map(&:author).uniq.each do |user|
if notify && user && user != @user && user.visible?

View file

@ -27,7 +27,7 @@ class OauthController < ApplicationController
end
def revoke
@token = current_user.oauth_tokens.find_by_token params[:token]
@token = current_user.oauth_tokens.find_by :token => params[:token]
if @token
@token.invalidate!
flash[:notice] = t("oauth.revoke.flash", :application => @token.client_application.name)
@ -49,7 +49,7 @@ class OauthController < ApplicationController
else
@token.oob? ? @token.client_application.callback_url : @token.callback_url
end
@redirect_url = URI.parse(callback_url) unless callback_url.blank?
@redirect_url = URI.parse(callback_url) if callback_url.present?
if @redirect_url.to_s.blank?
render :action => "authorize_success"

View file

@ -33,12 +33,12 @@ class OldController < ApplicationController
doc.root << element.to_xml_node
end
render :text => doc.to_s, :content_type => "text/xml"
render :xml => doc.to_s
end
def version
if @old_element.redacted? && !show_redactions?
render :text => "", :status => :forbidden
head :forbidden
else
response.last_modified = @old_element.timestamp
@ -46,7 +46,7 @@ class OldController < ApplicationController
doc = OSM::API.new.get_xml_doc
doc.root << @old_element.to_xml_node
render :text => doc.to_s, :content_type => "text/xml"
render :xml => doc.to_s
end
end
@ -64,7 +64,7 @@ class OldController < ApplicationController
end
# just return an empty 200 OK for success
render :text => ""
head :ok
end
private

View file

@ -32,11 +32,9 @@ class RedactionsController < ApplicationController
end
end
def show
end
def show; end
def edit
end
def edit; end
def update
# note - don't update the user ID

View file

@ -16,16 +16,16 @@ class RelationController < ApplicationController
# Assume that Relation.from_xml has thrown an exception if there is an error parsing the xml
relation.create_with_history @user
render :text => relation.id.to_s, :content_type => "text/plain"
render :plain => relation.id.to_s
end
def read
relation = Relation.find(params[:id])
response.last_modified = relation.timestamp
if relation.visible
render :text => relation.to_xml.to_s, :content_type => "text/xml"
render :xml => relation.to_xml.to_s
else
render :text => "", :status => :gone
head :gone
end
end
@ -40,7 +40,7 @@ class RelationController < ApplicationController
end
relation.update_from new_relation, @user
render :text => relation.version.to_s, :content_type => "text/plain"
render :plain => relation.version.to_s
end
def delete
@ -48,9 +48,9 @@ class RelationController < ApplicationController
new_relation = Relation.from_xml(request.raw_post)
if new_relation && new_relation.id == relation.id
relation.delete_with_history!(new_relation, @user)
render :text => relation.version.to_s, :content_type => "text/plain"
render :plain => relation.version.to_s
else
render :text => "", :status => :bad_request
head :bad_request
end
end
@ -119,10 +119,10 @@ class RelationController < ApplicationController
# finally add self and output
doc.root << relation.to_xml_node(visible_members, changeset_cache, user_display_name_cache)
render :text => doc.to_s, :content_type => "text/xml"
render :xml => doc.to_s
else
render :text => "", :status => :gone
head :gone
end
end
@ -143,7 +143,7 @@ class RelationController < ApplicationController
doc.root << relation.to_xml_node
end
render :text => doc.to_s, :content_type => "text/xml"
render :xml => doc.to_s
end
def relations_for_way
@ -167,6 +167,6 @@ class RelationController < ApplicationController
doc.root << relation.to_xml_node if relation.visible
end
render :text => doc.to_s, :content_type => "text/xml"
render :xml => doc.to_s
end
end

View file

@ -33,13 +33,13 @@ class SearchController < ApplicationController
if do_nodes
response.headers["Error"] = "Searching of nodes is currently unavailable"
render :text => "", :status => :service_unavailable
head :service_unavailable
return false
end
unless value
response.headers["Error"] = "Searching for a key without value is currently unavailable"
render :text => "", :status => :service_unavailable
head :service_unavailable
return false
end
@ -94,6 +94,6 @@ class SearchController < ApplicationController
doc.root << rel.to_xml_node(nil, changeset_cache, user_display_name_cache)
end
render :text => doc.to_s, :content_type => "text/xml"
render :xml => doc.to_s
end
end

View file

@ -8,6 +8,7 @@ class SiteController < ApplicationController
before_action :redirect_map_params, :only => [:index, :edit, :export]
before_action :require_user, :only => [:welcome]
before_action :require_oauth, :only => [:index]
before_action :update_totp, :only => [:index]
def index
unless STATUS == :database_readonly || STATUS == :database_offline
@ -49,7 +50,7 @@ class SiteController < ApplicationController
new_params[:anchor] = "map=#{zoom}/#{lat}/#{lon}"
new_params[:anchor] += "&layers=#{params[:layers]}" if params.key? :layers
redirect_to Hash[new_params]
redirect_to new_params.to_unsafe_h
end
def key
@ -68,6 +69,14 @@ class SiteController < ApplicationController
require_user
end
if %w[potlatch potlatch2].include?(editor)
append_content_security_policy_directives(
:object_src => %w[*],
:plugin_types => %w[application/x-shockwave-flash],
:script_src => %w['unsafe-inline']
)
end
if params[:node]
bbox = Node.find(params[:node]).bbox.to_unscaled
@lat = bbox.centre_lat
@ -83,7 +92,7 @@ class SiteController < ApplicationController
@lat = note.lat
@lon = note.lon
@zoom = 17
elsif params[:gpx]
elsif params[:gpx] && @user
trace = Trace.visible_to(@user).find(params[:gpx])
@lat = trace.latitude
@lon = trace.longitude
@ -95,26 +104,27 @@ class SiteController < ApplicationController
@locale = params[:copyright_locale] || I18n.locale
end
def welcome
end
def welcome; end
def help
end
def help; end
def about
end
def about; end
def export
end
def export; end
def offline
end
def offline; end
def preview
render :text => RichText.new(params[:format], params[:text]).to_html
render :html => RichText.new(params[:type], params[:text]).to_html
end
def id
append_content_security_policy_directives(
:connect_src => %w[taginfo.openstreetmap.org *.mapillary.com],
:img_src => %w[*],
:script_src => %w[dev.virtualearth.net]
)
render "id", :layout => false
end
@ -148,7 +158,7 @@ class SiteController < ApplicationController
end
if anchor.present?
redirect_to Hash[params].merge(:anchor => anchor.join("&"))
redirect_to params.to_unsafe_h.merge(:anchor => anchor.join("&"))
end
end
end

View file

@ -92,7 +92,7 @@ class SwfController < ApplicationController
m = pack_rect(bounds_left, bounds_right, bounds_bottom, bounds_top) + 0.chr + 12.chr + pack_u16(1) + m
m = "FWS" + 6.chr + pack_u32(m.length + 8) + m
render :text => m, :content_type => "application/x-shockwave-flash"
render :body => m, :content_type => "application/x-shockwave-flash"
end
private
@ -161,10 +161,10 @@ class SwfController < ApplicationController
def swf_record(id, r)
if r.length > 62
# Long header: tag id, 0x3F, length
return pack_u16((id << 6) + 0x3F) + pack_u32(r.length) + r
pack_u16((id << 6) + 0x3F) + pack_u32(r.length) + r
else
# Short header: tag id, length
return pack_u16((id << 6) + r.length) + r
pack_u16((id << 6) + r.length) + r
end
end
@ -195,7 +195,7 @@ class SwfController < ApplicationController
# Find number of bits required to store arbitrary-length binary
def length_sb(n)
Math.frexp(n + (n == 0 ? 1 : 0))[1] + 1
Math.frexp(n + (n.zero? ? 1 : 0))[1] + 1
end
# ====================================================================

View file

@ -21,7 +21,7 @@ class TraceController < ApplicationController
def list
# from display name, pick up user id if one user's traces only
display_name = params[:display_name]
unless display_name.blank?
if display_name.present?
target_user = User.active.where(:display_name => display_name).first
if target_user.nil?
render_unknown_user display_name
@ -59,11 +59,13 @@ class TraceController < ApplicationController
@traces = @traces.tagged(params[:tag]) if params[:tag]
@params = params.permit(:display_name, :tag)
@page = (params[:page] || 1).to_i
@page_size = 20
@traces = @traces.visible
@traces = @traces.order("timestamp DESC")
@traces = @traces.order(:id => :desc)
@traces = @traces.offset((@page - 1) * @page_size)
@traces = @traces.limit(@page_size)
@traces = @traces.includes(:user, :tags)
@ -95,15 +97,15 @@ class TraceController < ApplicationController
@title = t "trace.view.title", :name => @trace.name
else
flash[:error] = t "trace.view.trace_not_found"
redirect_to :controller => "trace", :action => "list"
redirect_to :action => "list"
end
rescue ActiveRecord::RecordNotFound
flash[:error] = t "trace.view.trace_not_found"
redirect_to :controller => "trace", :action => "list"
redirect_to :action => "list"
end
def create
if params[:trace]
if request.post?
logger.info(params[:trace][:gpx_file].class.name)
if params[:trace][:gpx_file].respond_to?(:read)
@ -145,32 +147,32 @@ class TraceController < ApplicationController
if trace.visible? && (trace.public? || (@user && @user == trace.user))
if Acl.no_trace_download(request.remote_ip)
render :text => "", :status => :forbidden
elsif request.format == Mime::XML
head :forbidden
elsif request.format == Mime[:xml]
send_file(trace.xml_file, :filename => "#{trace.id}.xml", :type => request.format.to_s, :disposition => "attachment")
elsif request.format == Mime::GPX
elsif request.format == Mime[:gpx]
send_file(trace.xml_file, :filename => "#{trace.id}.gpx", :type => request.format.to_s, :disposition => "attachment")
else
send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => "attachment")
end
else
render :text => "", :status => :not_found
head :not_found
end
rescue ActiveRecord::RecordNotFound
render :text => "", :status => :not_found
head :not_found
end
def edit
@trace = Trace.find(params[:id])
if !@trace.visible?
render :text => "", :status => :not_found
head :not_found
elsif @user.nil? || @trace.user != @user
render :text => "", :status => :forbidden
head :forbidden
else
@title = t "trace.edit.title", :name => @trace.name
if params[:trace]
if request.post? && params[:trace]
@trace.description = params[:trace][:description]
@trace.tagstring = params[:trace][:tagstring]
@trace.visibility = params[:trace][:visibility]
@ -180,16 +182,16 @@ class TraceController < ApplicationController
end
end
rescue ActiveRecord::RecordNotFound
render :text => "", :status => :not_found
head :not_found
end
def delete
trace = Trace.find(params[:id])
if !trace.visible?
render :text => "", :status => :not_found
head :not_found
elsif @user.nil? || trace.user != @user
render :text => "", :status => :forbidden
head :forbidden
else
trace.visible = false
trace.save
@ -197,7 +199,7 @@ class TraceController < ApplicationController
redirect_to :action => :list, :display_name => @user.display_name
end
rescue ActiveRecord::RecordNotFound
render :text => "", :status => :not_found
head :not_found
end
def georss
@ -221,13 +223,13 @@ class TraceController < ApplicationController
expires_in 7.days, :private => !trace.public?, :public => trace.public?
send_file(trace.large_picture_name, :filename => "#{trace.id}.gif", :type => "image/gif", :disposition => "inline")
else
render :text => "", :status => :forbidden
head :forbidden
end
else
render :text => "", :status => :not_found
head :not_found
end
rescue ActiveRecord::RecordNotFound
render :text => "", :status => :not_found
head :not_found
end
def icon
@ -238,22 +240,22 @@ class TraceController < ApplicationController
expires_in 7.days, :private => !trace.public?, :public => trace.public?
send_file(trace.icon_picture_name, :filename => "#{trace.id}_icon.gif", :type => "image/gif", :disposition => "inline")
else
render :text => "", :status => :forbidden
head :forbidden
end
else
render :text => "", :status => :not_found
head :not_found
end
rescue ActiveRecord::RecordNotFound
render :text => "", :status => :not_found
head :not_found
end
def api_read
trace = Trace.visible.find(params[:id])
if trace.public? || trace.user == @user
render :text => trace.to_xml.to_s, :content_type => "text/xml"
render :xml => trace.to_xml.to_s
else
render :text => "", :status => :forbidden
head :forbidden
end
end
@ -272,9 +274,9 @@ class TraceController < ApplicationController
trace.visibility = new_trace.visibility
trace.save!
render :text => "", :status => :ok
head :ok
else
render :text => "", :status => :forbidden
head :forbidden
end
end
@ -285,9 +287,9 @@ class TraceController < ApplicationController
trace.visible = false
trace.save!
render :text => "", :status => :ok
head :ok
else
render :text => "", :status => :forbidden
head :forbidden
end
end
@ -295,15 +297,15 @@ class TraceController < ApplicationController
trace = Trace.visible.find(params[:id])
if trace.public? || trace.user == @user
if request.format == Mime::XML
if request.format == Mime[:xml]
send_file(trace.xml_file, :filename => "#{trace.id}.xml", :type => request.format.to_s, :disposition => "attachment")
elsif request.format == Mime::GPX
elsif request.format == Mime[:gpx]
send_file(trace.xml_file, :filename => "#{trace.id}.gpx", :type => request.format.to_s, :disposition => "attachment")
else
send_file(trace.trace_name, :filename => "#{trace.id}#{trace.extension_name}", :type => trace.mime_type, :disposition => "attachment")
end
else
render :text => "", :status => :forbidden
head :forbidden
end
end
@ -324,14 +326,14 @@ class TraceController < ApplicationController
do_create(params[:file], tags, description, visibility)
if @trace.id
render :text => @trace.id.to_s, :content_type => "text/plain"
render :plain => @trace.id.to_s
elsif @trace.valid?
render :text => "", :status => :internal_server_error
head :internal_server_error
else
render :text => "", :status => :bad_request
head :bad_request
end
else
render :text => "", :status => :bad_request
head :bad_request
end
end

View file

@ -12,6 +12,7 @@ class UserBlocksController < ApplicationController
before_action :check_database_writable, :only => [:create, :update, :revoke]
def index
@params = params.permit
@user_blocks_pages, @user_blocks = paginate(:user_blocks,
:include => [:user, :creator, :revoker],
:order => "user_blocks.ends_at DESC",
@ -88,6 +89,7 @@ class UserBlocksController < ApplicationController
##
# shows a list of all the blocks on the given user
def blocks_on
@params = params.permit(:display_name)
@user_blocks_pages, @user_blocks = paginate(:user_blocks,
:include => [:user, :creator, :revoker],
:conditions => { :user_id => @this_user.id },
@ -98,6 +100,7 @@ class UserBlocksController < ApplicationController
##
# shows a list of all the blocks by the given user.
def blocks_by
@params = params.permit(:display_name)
@user_blocks_pages, @user_blocks = paginate(:user_blocks,
:include => [:user, :creator, :revoker],
:conditions => { :creator_id => @this_user.id },

View file

@ -81,7 +81,7 @@ class UserController < ApplicationController
@user.terms_agreed = Time.now.getutc
@user.terms_seen = true
if @user.auth_uid.nil? || @user.auth_uid.empty?
if @user.auth_uid.blank?
@user.auth_provider = nil
@user.auth_uid = nil
end
@ -142,14 +142,14 @@ class UserController < ApplicationController
@user.data_public = true
@user.save
flash[:notice] = t "user.go_public.flash success"
redirect_to :controller => "user", :action => "account", :display_name => @user.display_name
redirect_to :action => "account", :display_name => @user.display_name
end
def lost_password
@title = t "user.lost_password.title"
if params[:user] && params[:user][:email]
user = User.visible.find_by_email(params[:user][:email])
user = User.visible.find_by(:email => params[:user][:email])
if user.nil?
users = User.visible.where("LOWER(email) = LOWER(?)", params[:user][:email])
@ -172,7 +172,7 @@ class UserController < ApplicationController
@title = t "user.reset_password.title"
if params[:token]
token = UserToken.find_by_token(params[:token])
token = UserToken.find_by(:token => params[:token])
if token
@user = token.user
@ -194,7 +194,7 @@ class UserController < ApplicationController
redirect_to :action => "lost_password"
end
else
render :text => "", :status => :bad_request
head :bad_request
end
end
@ -268,9 +268,9 @@ class UserController < ApplicationController
def logout
@title = t "user.logout.title"
if params[:session] == request.session_options[:id]
if params[:session] == session.id
if session[:token]
token = UserToken.find_by_token(session[:token])
token = UserToken.find_by(:token => session[:token])
token.destroy if token
session.delete(:token)
end
@ -286,7 +286,7 @@ class UserController < ApplicationController
def confirm
if request.post?
token = UserToken.find_by_token(params[:confirm_string])
token = UserToken.find_by(:token => params[:confirm_string])
if token && token.user.active?
flash[:error] = t("user.confirm.already active")
redirect_to :action => "login"
@ -303,7 +303,7 @@ class UserController < ApplicationController
token.destroy
if session[:token]
token = UserToken.find_by_token(session[:token])
token = UserToken.find_by(:token => session[:token])
session.delete(:token)
else
token = nil
@ -321,15 +321,15 @@ class UserController < ApplicationController
end
end
else
user = User.find_by_display_name(params[:display_name])
user = User.find_by(:display_name => params[:display_name])
redirect_to root_path if user.nil? || user.active?
end
end
def confirm_resend
user = User.find_by_display_name(params[:display_name])
token = UserToken.find_by_token(session[:token])
user = User.find_by(:display_name => params[:display_name])
token = UserToken.find_by(:token => session[:token])
if user.nil? || token.nil? || token.user != user
flash[:error] = t "user.confirm_resend.failure", :name => params[:display_name]
@ -343,7 +343,7 @@ class UserController < ApplicationController
def confirm_email
if request.post?
token = UserToken.find_by_token(params[:confirm_string])
token = UserToken.find_by(:token => params[:confirm_string])
if token && token.user.new_email?
@user = token.user
@user.email = @user.new_email
@ -375,7 +375,7 @@ class UserController < ApplicationController
if @this_user.visible?
render :action => :api_read, :content_type => "text/xml"
else
render :text => "", :status => :gone
head :gone
end
end
@ -389,11 +389,11 @@ class UserController < ApplicationController
@user.traces.reload.each do |trace|
doc.root << trace.to_xml_node
end
render :text => doc.to_s, :content_type => "text/xml"
render :xml => doc.to_s
end
def view
@this_user = User.find_by_display_name(params[:display_name])
@this_user = User.find_by(:display_name => params[:display_name])
if @this_user &&
(@this_user.visible? || (@user && @user.administrator?))
@ -404,7 +404,7 @@ class UserController < ApplicationController
end
def make_friend
@new_friend = User.find_by_display_name(params[:display_name])
@new_friend = User.find_by(:display_name => params[:display_name])
if @new_friend
if request.post?
@ -423,7 +423,7 @@ class UserController < ApplicationController
if params[:referer]
redirect_to params[:referer]
else
redirect_to :controller => "user", :action => "view"
redirect_to :action => "view"
end
end
else
@ -432,12 +432,12 @@ class UserController < ApplicationController
end
def remove_friend
@friend = User.find_by_display_name(params[:display_name])
@friend = User.find_by(:display_name => params[:display_name])
if @friend
if request.post?
if @user.is_friends_with?(@friend)
Friend.delete_all "user_id = #{@user.id} AND friend_user_id = #{@friend.id}"
Friend.where(:user_id => @user.id, :friend_user_id => @friend.id).delete_all
flash[:notice] = t "user.remove_friend.success", :name => @friend.display_name
else
flash[:error] = t "user.remove_friend.not_a_friend", :name => @friend.display_name
@ -446,7 +446,7 @@ class UserController < ApplicationController
if params[:referer]
redirect_to params[:referer]
else
redirect_to :controller => "user", :action => "view"
redirect_to :action => "view"
end
end
else
@ -459,14 +459,14 @@ class UserController < ApplicationController
def set_status
@this_user.status = params[:status]
@this_user.save
redirect_to :controller => "user", :action => "view", :display_name => params[:display_name]
redirect_to :action => "view", :display_name => params[:display_name]
end
##
# delete a user, marking them as deleted and removing personal data
def delete
@this_user.delete
redirect_to :controller => "user", :action => "view", :display_name => params[:display_name]
redirect_to :action => "view", :display_name => params[:display_name]
end
##
@ -480,9 +480,11 @@ class UserController < ApplicationController
redirect_to url_for(:status => params[:status], :ip => params[:ip], :page => params[:page])
else
@params = params.permit(:status, :ip)
conditions = {}
conditions[:status] = params[:status] if params[:status]
conditions[:creation_ip] = params[:ip] if params[:ip]
conditions[:status] = @params[:status] if @params[:status]
conditions[:creation_ip] = @params[:ip] if @params[:ip]
@user_pages, @users = paginate(:users,
:conditions => conditions,
@ -494,7 +496,7 @@ class UserController < ApplicationController
##
# omniauth success callback
def auth_success
auth_info = env["omniauth.auth"]
auth_info = request.env["omniauth.auth"]
provider = auth_info[:provider]
uid = auth_info[:uid]
@ -530,11 +532,11 @@ class UserController < ApplicationController
redirect_to :action => "terms"
else
user = User.find_by_auth_provider_and_auth_uid(provider, uid)
user = User.find_by(:auth_provider => provider, :auth_uid => uid)
if user.nil? && provider == "google"
openid_url = auth_info[:extra][:id_info]["openid_id"]
user = User.find_by_auth_provider_and_auth_uid("openid", openid_url) if openid_url
user = User.find_by(:auth_provider => "openid", :auth_uid => openid_url) if openid_url
user.update(:auth_provider => provider, :auth_uid => uid) if user
end
@ -543,7 +545,7 @@ class UserController < ApplicationController
when "pending" then
unconfirmed_login(user)
when "active", "confirmed" then
successful_login(user, env["omniauth.params"]["referer"])
successful_login(user, request.env["omniauth.params"]["referer"])
when "suspended" then
failed_login t("user.login.account is suspended", :webmaster => "mailto:#{SUPPORT_EMAIL}")
else
@ -601,15 +603,15 @@ class UserController < ApplicationController
# try and come up with the correct URL based on what the user entered
def openid_expand_url(openid_url)
if openid_url.nil?
return nil
nil
elsif openid_url.match(%r{(.*)gmail.com(/?)$}) || openid_url.match(%r{(.*)googlemail.com(/?)$})
# Special case gmail.com as it is potentially a popular OpenID
# provider and, unlike yahoo.com, where it works automatically, Google
# have hidden their OpenID endpoint somewhere obscure this making it
# somewhat less user friendly.
return "https://www.google.com/accounts/o8/id"
"https://www.google.com/accounts/o8/id"
else
return openid_url
openid_url
end
end
@ -628,7 +630,7 @@ class UserController < ApplicationController
# - If they were referred to the login, send them back there.
# - Otherwise, send them to the home page.
if REQUIRE_TERMS_SEEN && !user.terms_seen
redirect_to :controller => :user, :action => :terms, :referer => target
redirect_to :action => :terms, :referer => target
elsif user.blocked_on_view
redirect_to user.blocked_on_view, :referer => target
else
@ -723,8 +725,8 @@ class UserController < ApplicationController
# Ignore errors sending email
end
else
@user.errors.set(:new_email, @user.errors.get(:email))
@user.errors.set(:email, [])
@user.errors.add(:new_email, @user.errors[:email])
@user.errors.add(:email, [])
end
user.restore_email!
@ -740,21 +742,19 @@ class UserController < ApplicationController
flash[:error] = t("user.filter.not_an_administrator")
if params[:display_name]
redirect_to :controller => "user", :action => "view", :display_name => params[:display_name]
redirect_to :action => "view", :display_name => params[:display_name]
else
redirect_to :controller => "user", :action => "login", :referer => request.fullpath
redirect_to :action => "login", :referer => request.fullpath
end
elsif !@user
redirect_to :controller => "user", :action => "login", :referer => request.fullpath
redirect_to :action => "login", :referer => request.fullpath
end
end
##
# require that the user in the URL is the logged in user
def require_self
if params[:display_name] != @user.display_name
render :text => "", :status => :forbidden
end
head :forbidden if params[:display_name] != @user.display_name
end
##
@ -766,9 +766,9 @@ class UserController < ApplicationController
##
# ensure that there is a "this_user" instance variable
def lookup_user_by_name
@this_user = User.find_by_display_name(params[:display_name])
@this_user = User.find_by(:display_name => params[:display_name])
rescue ActiveRecord::RecordNotFound
redirect_to :controller => "user", :action => "view", :display_name => params[:display_name] unless @this_user
redirect_to :action => "view", :display_name => params[:display_name] unless @this_user
end
##
@ -823,9 +823,9 @@ class UserController < ApplicationController
# display a message about th current status of the gravatar setting
def gravatar_status_message(user)
if user.image_use_gravatar
return t "user.account.gravatar.enabled"
t "user.account.gravatar.enabled"
else
return t "user.account.gravatar.disabled"
t "user.account.gravatar.disabled"
end
end
end

View file

@ -20,7 +20,7 @@ class UserPreferenceController < ApplicationController
end
doc.root << el1
render :text => doc.to_s, :content_type => "text/xml"
render :xml => doc.to_s
end
##
@ -28,7 +28,7 @@ class UserPreferenceController < ApplicationController
def read_one
pref = UserPreference.find([@user.id, params[:preference_key]])
render :text => pref.v.to_s, :content_type => "text/plain"
render :plain => pref.v.to_s
end
# update the entire set of preferences
@ -39,7 +39,7 @@ class UserPreferenceController < ApplicationController
new_preferences = {}
doc = XML::Parser.string(request.raw_post).parse
doc = XML::Parser.string(request.raw_post, :options => XML::Parser::Options::NOERROR).parse
doc.find("//preferences/preference").each do |pt|
if preference = old_preferences.delete(pt["k"])
@ -57,7 +57,7 @@ class UserPreferenceController < ApplicationController
new_preferences.each_value(&:save!)
render :text => "", :content_type => "text/plain"
render :plain => ""
end
##
@ -74,7 +74,7 @@ class UserPreferenceController < ApplicationController
pref.v = request.raw_post.chomp
pref.save!
render :text => "", :content_type => "text/plain"
render :plain => ""
end
##
@ -82,6 +82,6 @@ class UserPreferenceController < ApplicationController
def delete_one
UserPreference.find([@user.id, params[:preference_key]]).delete
render :text => "", :content_type => "text/plain"
render :plain => ""
end
end

View file

@ -15,7 +15,7 @@ class UserRolesController < ApplicationController
end
def revoke
UserRole.delete_all(:user_id => @this_user.id, :role => @role)
UserRole.where(:user_id => @this_user.id, :role => @role).delete_all
redirect_to :controller => "user", :action => "view", :display_name => @this_user.display_name
end

View file

@ -16,7 +16,7 @@ class WayController < ApplicationController
# Assume that Way.from_xml has thrown an exception if there is an error parsing the xml
way.create_with_history @user
render :text => way.id.to_s, :content_type => "text/plain"
render :plain => way.id.to_s
end
def read
@ -25,9 +25,9 @@ class WayController < ApplicationController
response.last_modified = way.timestamp
if way.visible
render :text => way.to_xml.to_s, :content_type => "text/xml"
render :xml => way.to_xml.to_s
else
render :text => "", :status => :gone
head :gone
end
end
@ -40,7 +40,7 @@ class WayController < ApplicationController
end
way.update_from(new_way, @user)
render :text => way.version.to_s, :content_type => "text/plain"
render :plain => way.version.to_s
end
# This is the API call to delete a way
@ -50,9 +50,9 @@ class WayController < ApplicationController
if new_way && new_way.id == way.id
way.delete_with_history!(new_way, @user)
render :text => way.version.to_s, :content_type => "text/plain"
render :plain => way.version.to_s
else
render :text => "", :status => :bad_request
head :bad_request
end
end
@ -73,9 +73,9 @@ class WayController < ApplicationController
end
doc.root << way.to_xml_node(visible_nodes, changeset_cache, user_display_name_cache)
render :text => doc.to_s, :content_type => "text/xml"
render :xml => doc.to_s
else
render :text => "", :status => :gone
head :gone
end
end
@ -96,7 +96,7 @@ class WayController < ApplicationController
doc.root << way.to_xml_node
end
render :text => doc.to_s, :content_type => "text/xml"
render :xml => doc.to_s
end
##
@ -112,6 +112,6 @@ class WayController < ApplicationController
doc.root << way.to_xml_node if way.visible
end
render :text => doc.to_s, :content_type => "text/xml"
render :xml => doc.to_s
end
end

View file

@ -59,16 +59,16 @@ module ApplicationHelper
def richtext_area(object_name, method, options = {})
id = "#{object_name}_#{method}"
format = options.delete(:format) || "markdown"
type = options.delete(:format) || "markdown"
content_tag(:div, :id => "#{id}_container", :class => "richtext_container") do
output_buffer << content_tag(:div, :id => "#{id}_content", :class => "richtext_content") do
output_buffer << text_area(object_name, method, options.merge("data-preview-url" => preview_url(:format => format)))
output_buffer << text_area(object_name, method, options.merge("data-preview-url" => preview_url(:type => type)))
output_buffer << content_tag(:div, "", :id => "#{id}_preview", :class => "richtext_preview richtext")
end
output_buffer << content_tag(:div, :id => "#{id}_help", :class => "richtext_help") do
output_buffer << render("site/#{format}_help")
output_buffer << render("site/#{type}_help")
output_buffer << content_tag(:div, :class => "buttons") do
output_buffer << submit_tag(I18n.t("site.richtext_area.edit"), :id => "#{id}_doedit", :class => "richtext_doedit deemphasize", :disabled => true)
output_buffer << submit_tag(I18n.t("site.richtext_area.preview"), :id => "#{id}_dopreview", :class => "richtext_dopreview deemphasize")
@ -100,4 +100,30 @@ module ApplicationHelper
def current_page_class(path)
:current if current_page?(path)
end
def application_data
data = {
:locale => I18n.locale,
:preferred_editor => preferred_editor
}
if @user
data[:user] = @user.id.to_json
unless @user.home_lon.nil? || @user.home_lat.nil?
data[:user_home] = { :lat => @user.home_lat, :lon => @user.home_lon }
end
end
data[:location] = session[:location] if session[:location]
if @oauth
data[:token] = @oauth.token
data[:token_secret] = @oauth.secret
data[:consumer_key] = @oauth.client_application.key
data[:consumer_secret] = @oauth.client_application.secret
end
data
end
end

View file

@ -7,7 +7,7 @@ module BannerHelper
rescue
parsed = nil
end
parsed.is_a?(Date) && parsed.past?
!parsed.is_a?(Date) || (parsed.is_a?(Date) && parsed.past?)
end
end
@ -17,6 +17,7 @@ module BannerHelper
banner_key = nil
cookie_key = nil
min_index = 9999
min_date = Date.new(9999, 1, 1)
banners.each do |k, v|
ckey = banner_cookie(v[:id]).to_sym
@ -30,9 +31,14 @@ module BannerHelper
# pick banner with mininum queue position
next if index > min_index
# or if equal queue position, pick banner with soonest end date (i.e. next expiring)
end_date = Date.parse(v[:enddate])
next if index == min_index && end_date > min_date
banner_key = k
cookie_key = ckey
min_index = index
min_date = end_date
end
unless banner_key.nil?

View file

@ -99,7 +99,7 @@ module BrowseHelper
private
ICON_TAGS = %w(aeroway amenity barrier building highway historic landuse leisure man_made natural railway shop tourism waterway).freeze
ICON_TAGS = %w[aeroway amenity barrier building highway historic landuse leisure man_made natural railway shop tourism waterway].freeze
def icon_tags(object)
object.tags.find_all { |k, _v| ICON_TAGS.include? k }.sort
@ -133,14 +133,14 @@ module BrowseHelper
lang = if value =~ /^([a-z-]{2,12}):(.+)$/i
# Value is <lang>:<title> so split it up
# Note that value is always left as-is, see: https://trac.openstreetmap.org/ticket/4315
$1
Regexp.last_match(1)
else
# Value is <title> so default to English Wikipedia
"en"
end
elsif key =~ /^wikipedia:(\S+)$/
# Language is in the key, so assume value is the title
lang = $1
lang = Regexp.last_match(1)
else
# Not a wikipedia key!
return nil
@ -149,9 +149,9 @@ module BrowseHelper
if value =~ /^([^#]*)#(.*)/
# Contains a reference to a section of the wikipedia article
# Must break it up to correctly build the url
value = $1
section = "#" + $2
encoded_section = "#" + URI.encode($2.gsub(/ +/, "_"), /[^A-Za-z0-9:_]/).tr("%", ".")
value = Regexp.last_match(1)
section = "#" + Regexp.last_match(2)
encoded_section = "#" + URI.encode(Regexp.last_match(2).gsub(/ +/, "_"), /[^A-Za-z0-9:_]/).tr("%", ".")
else
section = ""
encoded_section = ""

View file

@ -2,4 +2,33 @@ module NotifierHelper
def fp(text)
format_paragraph(text, 72, 0)
end
def link_to_user(display_name)
link_to(
content_tag(
"strong",
display_name,
# NB we need "text-decoration: none" twice: GMail only honours it on
# the <a> but Outlook only on the <strong>
:style => "text-decoration: none"
),
user_url(display_name, :host => SERVER_URL),
:target => "_blank",
:style => "text-decoration: none; color: #222"
)
end
def message_body(&block)
render(
:partial => "message_body",
:locals => { :body => capture(&block) }
)
end
def style_message(html)
# Because we can't use stylesheets in HTML emails, we need to inline the
# styles. Rather than copy-paste the same string of CSS into every message,
# we apply it once here, after the message has been composed.
html.gsub /<p>/, '<p style="color: black; margin: 0.75em 0; font-family: \'Helvetica Neue\', Arial, Sans-Serif">'
end
end

View file

@ -4,9 +4,9 @@ module OpenGraphHelper
"og:site_name" => t("layouts.project_name.title"),
"og:title" => [t("layouts.project_name.title"), title].compact.join(" | "),
"og:type" => "website",
"og:image" => image_path("osm_logo_256.png", :host => SERVER_URL, :protocol => "http"),
"og:image:secure_url" => image_path("osm_logo_256.png", :host => SERVER_URL, :protocol => "https"),
"og:url" => url_for(:host => SERVER_URL),
"og:image" => image_url("osm_logo_256.png", :protocol => "http"),
"og:image:secure_url" => image_url("osm_logo_256.png", :protocol => "https"),
"og:url" => url_for(:only_path => false),
"og:description" => t("layouts.intro_text")
}

View file

@ -1,9 +1,9 @@
module TraceHelper
def link_to_tag(tag)
if @action == "mine"
return link_to(tag, :tag => tag, :page => nil)
link_to(tag, :tag => tag, :page => nil)
else
return link_to(tag, :tag => tag, :display_name => @display_name, :page => nil)
link_to(tag, :tag => tag, :display_name => @display_name, :page => nil)
end
end
end

View file

@ -4,8 +4,13 @@ module UserBlocksHelper
# user block (i.e: whether it's active, what the expiry time is)
def block_status(block)
if block.active?
# if the block hasn't expired yet show the date, if the user just needs to login show that
if block.needs_view?
I18n.t("user_block.helper.until_login")
if block.ends_at > Time.now.getutc
I18n.t("user_block.helper.time_future_and_until_login", :time => friendly_date(block.ends_at)).html_safe
else
I18n.t("user_block.helper.until_login")
end
else
I18n.t("user_block.helper.time_future", :time => friendly_date(block.ends_at)).html_safe
end

View file

@ -57,6 +57,8 @@ module UserHelper
)
end
private
# Gravatar support
# See http://en.gravatar.com/site/implement/images/ for details.

View file

@ -1,6 +1,8 @@
module UserRolesHelper
def role_icons(user)
UserRole::ALL_ROLES.reduce("".html_safe) { |a, e| a + " " + role_icon(user, e) }
UserRole::ALL_ROLES.reduce("".html_safe) do |acc, elem|
acc + " " + role_icon(user, elem)
end
end
def role_icon(user, role)

View file

@ -1,4 +1,6 @@
class Acl < ActiveRecord::Base
validates :k, :presence => true
def self.match(address, domain = nil)
if domain
Acl.where("address >>= ? OR domain = ?", address, domain)

View file

@ -32,7 +32,7 @@ class Changeset < ActiveRecord::Base
EXPAND = 0.1
# maximum number of elements allowed in a changeset
MAX_ELEMENTS = 50000
MAX_ELEMENTS = 10000
# maximum time a changeset is allowed to be open for.
MAX_TIME_OPEN = 1.day
@ -149,7 +149,7 @@ class Changeset < ActiveRecord::Base
save!
tags = self.tags
ChangesetTag.delete_all(:changeset_id => id)
ChangesetTag.where(:changeset_id => id).delete_all
tags.each do |k, v|
tag = ChangesetTag.new

View file

@ -18,7 +18,7 @@ class ClientApplication < ActiveRecord::Base
attr_accessor :token_callback_url
def self.find_token(token_key)
token = OauthToken.find_by_token(token_key, :include => :client_application)
token = OauthToken.includes(:client_application).find_by(:token => token_key)
token if token && token.authorized?
end
@ -75,9 +75,7 @@ class ClientApplication < ActiveRecord::Base
# this is the set of permissions that the client can ask for. clients
# have to say up-front what permissions they want and when users sign up they
# can agree or not agree to each of them.
PERMISSIONS = [:allow_read_prefs, :allow_write_prefs, :allow_write_diary,
:allow_write_api, :allow_read_gpx, :allow_write_gpx,
:allow_write_notes].freeze
PERMISSIONS = [:allow_read_prefs, :allow_write_prefs, :allow_write_diary, :allow_write_api, :allow_read_gpx, :allow_write_gpx, :allow_write_notes].freeze
def generate_keys
self.key = OAuth::Helper.generate_key(40)[0, 40]

View file

@ -3,7 +3,9 @@ class DiaryEntry < ActiveRecord::Base
belongs_to :language, :foreign_key => "language_code"
has_many :comments, -> { order(:id).preload(:user) }, :class_name => "DiaryComment"
has_many :visible_comments, -> { joins(:user).where(:visible => true, :users => { :status => %w(active confirmed) }).order(:id) }, :class_name => "DiaryComment"
has_many :visible_comments, -> { joins(:user).where(:visible => true, :users => { :status => %w[active confirmed] }).order(:id) }, :class_name => "DiaryComment"
has_many :subscriptions, :class_name => "DiaryEntrySubscription"
has_many :subscribers, :through => :subscriptions, :source => :user
scope :visible, -> { where(:visible => true) }

View file

@ -0,0 +1,6 @@
class DiaryEntrySubscription < ActiveRecord::Base
self.primary_keys = "user_id", "diary_entry_id"
belongs_to :user
belongs_to :diary_entry
end

View file

@ -5,7 +5,7 @@ class Language < ActiveRecord::Base
def self.load(file)
Language.transaction do
YAML.load(File.read(file)).each do |k, v|
YAML.safe_load(File.read(file)).each do |k, v|
begin
Language.update(k, :english_name => v["english"], :native_name => v["native"])
rescue ActiveRecord::RecordNotFound

View file

@ -49,7 +49,7 @@ class Node < ActiveRecord::Base
# Read in xml as text and return it's Node object representation
def self.from_xml(xml, create = false)
p = XML::Parser.string(xml)
p = XML::Parser.string(xml, :options => XML::Parser::Options::NOERROR)
doc = p.parse
doc.find("//osm/node").each do |pt|
@ -81,7 +81,7 @@ class Node < ActiveRecord::Base
node.id = pt["id"].to_i
# .to_i will return 0 if there is no number that can be parsed.
# We want to make sure that there is no id with zero anyway
raise OSM::APIBadUserInput.new("ID of node cannot be zero when updating.") if node.id == 0
raise OSM::APIBadUserInput.new("ID of node cannot be zero when updating.") if node.id.zero?
end
# We don't care about the time, as it is explicitly set on create/update/delete
@ -120,10 +120,10 @@ class Node < ActiveRecord::Base
lock!
check_consistency(self, new_node, user)
ways = Way.joins(:way_nodes).where(:visible => true, :current_way_nodes => { :node_id => id }).order(:id)
raise OSM::APIPreconditionFailedError.new("Node #{id} is still used by ways #{ways.collect(&:id).join(",")}.") unless ways.empty?
raise OSM::APIPreconditionFailedError.new("Node #{id} is still used by ways #{ways.collect(&:id).join(',')}.") unless ways.empty?
rels = Relation.joins(:relation_members).where(:visible => true, :current_relation_members => { :member_type => "Node", :member_id => id }).order(:id)
raise OSM::APIPreconditionFailedError.new("Node #{id} is still used by relations #{rels.collect(&:id).join(",")}.") unless rels.empty?
raise OSM::APIPreconditionFailedError.new("Node #{id} is still used by relations #{rels.collect(&:id).join(',')}.") unless rels.empty?
self.changeset_id = new_node.changeset_id
self.tags = {}
@ -232,14 +232,18 @@ class Node < ActiveRecord::Base
def save_with_history!
t = Time.now.getutc
self.version += 1
self.timestamp = t
Node.transaction do
self.version += 1
self.timestamp = t
save!
# clone the object before saving it so that the original is
# still marked as dirty if we retry the transaction
clone.save!
# Create a NodeTag
tags = self.tags
NodeTag.delete_all(:node_id => id)
NodeTag.where(:node_id => id).delete_all
tags.each do |k, v|
tag = NodeTag.new
tag.node_id = id

View file

@ -7,7 +7,7 @@ class Note < ActiveRecord::Base
:numericality => { :on => :update, :integer_only => true }
validates :latitude, :longitude, :numericality => { :only_integer => true }
validates :closed_at, :presence => true, :if => proc { :status == "closed" }
validates :status, :inclusion => %w(open closed hidden)
validates :status, :inclusion => %w[open closed hidden]
validate :validate_position

View file

@ -7,7 +7,7 @@ class NoteComment < ActiveRecord::Base
validates :note, :presence => true, :associated => true
validates :visible, :inclusion => [true, false]
validates :author, :associated => true
validates :event, :inclusion => %w(opened closed reopened commented hidden)
validates :event, :inclusion => %w[opened closed reopened commented hidden]
validates :body, :format => /\A[^\x00-\x08\x0b-\x0c\x0e-\x1f\x7f\ufffe\uffff]*\z/
# Return the comment text

View file

@ -3,6 +3,8 @@ class Notifier < ActionMailer::Base
:return_path => EMAIL_RETURN_PATH,
:auto_submitted => "auto-generated"
helper :application
before_action :set_shared_template_vars
before_action :attach_project_logo
def signup_confirm(user, token)
with_recipient_locale user do
@ -76,6 +78,9 @@ class Notifier < ActionMailer::Base
@replyurl = url_for(:host => SERVER_URL,
:controller => "message", :action => "reply",
:message_id => message.id)
@author = @from_user
attach_user_avatar(message.sender)
mail :from => from_address(message.sender.display_name, "m", message.id, message.digest),
:to => message.recipient.email,
@ -83,9 +88,9 @@ class Notifier < ActionMailer::Base
end
end
def diary_comment_notification(comment)
with_recipient_locale comment.diary_entry.user do
@to_user = comment.diary_entry.user.display_name
def diary_comment_notification(comment, recipient)
with_recipient_locale recipient do
@to_user = recipient.display_name
@from_user = comment.user.display_name
@text = comment.body
@title = comment.diary_entry.title
@ -106,9 +111,12 @@ class Notifier < ActionMailer::Base
:action => "new",
:display_name => comment.user.display_name,
:title => "Re: #{comment.diary_entry.title}")
@author = @from_user
mail :from => from_address(comment.user.display_name, "c", comment.id, comment.digest),
:to => comment.diary_entry.user.email,
attach_user_avatar(comment.user)
mail :from => from_address(comment.user.display_name, "c", comment.id, comment.digest, recipient.id),
:to => recipient.email,
:subject => I18n.t("notifier.diary_comment_notification.subject", :user => comment.user.display_name)
end
end
@ -122,7 +130,9 @@ class Notifier < ActionMailer::Base
@friendurl = url_for(:host => SERVER_URL,
:controller => "user", :action => "make_friend",
:display_name => @friend.befriender.display_name)
@author = @friend.befriender.display_name
attach_user_avatar(@friend.befriender)
mail :to => friend.befriendee.email,
:subject => I18n.t("notifier.friend_notification.subject", :user => friend.befriender.display_name)
end
@ -142,6 +152,9 @@ class Notifier < ActionMailer::Base
I18n.t("notifier.note_comment_notification.anonymous")
end
@author = @commenter
attach_user_avatar(comment.author)
subject = if @owner
I18n.t("notifier.note_comment_notification.#{@event}.subject_own", :commenter => @commenter)
else
@ -154,6 +167,7 @@ class Notifier < ActionMailer::Base
def changeset_comment_notification(comment, recipient)
with_recipient_locale recipient do
@to_user = recipient.display_name
@changeset_url = changeset_url(comment.changeset, :host => SERVER_URL)
@comment = comment.body
@owner = recipient == comment.changeset.user
@ -161,6 +175,7 @@ class Notifier < ActionMailer::Base
@changeset_comment = comment.changeset.tags["comment"].presence
@time = comment.created_at
@changeset_author = comment.changeset.user.display_name
@author = @commenter
subject = if @owner
I18n.t("notifier.changeset_comment_notification.commented.subject_own", :commenter => @commenter)
@ -168,6 +183,8 @@ class Notifier < ActionMailer::Base
I18n.t("notifier.changeset_comment_notification.commented.subject_other", :commenter => @commenter)
end
attach_user_avatar(comment.author)
mail :to => recipient.email, :subject => subject
end
end
@ -185,15 +202,40 @@ class Notifier < ActionMailer::Base
private
def set_shared_template_vars
@root_url = root_url(:host => SERVER_URL)
end
def attach_project_logo
attachments.inline["logo.png"] = File.read(Rails.root.join("app", "assets", "images", "osm_logo_30.png"))
end
def attach_user_avatar(user)
attachments.inline["avatar.png"] = File.read(user_avatar_file_path(user))
end
def user_avatar_file_path(user)
image = user && user.image
if image && image.file?
return image.path(:small)
else
return Rails.root.join("app", "assets", "images", "users", "images", "small.png")
end
end
def with_recipient_locale(recipient)
I18n.with_locale Locale.available.preferred(recipient.preferred_languages) do
yield
end
end
def from_address(name, type, id, digest)
def from_address(name, type, id, digest, user_id = nil)
if Object.const_defined?(:MESSAGES_DOMAIN) && domain = MESSAGES_DOMAIN
"#{name} <#{type}-#{id}-#{digest[0, 6]}@#{domain}>"
if user_id
"#{name} <#{type}-#{id}-#{user_id}-#{digest[0, 6]}@#{domain}>"
else
"#{name} <#{type}-#{id}-#{digest[0, 6]}@#{domain}>"
end
else
EMAIL_FROM
end

View file

@ -6,7 +6,8 @@ class OauthNonce < ActiveRecord::Base
# Remembers a nonce and it's associated timestamp. It returns false if it has already been used
def self.remember(nonce, timestamp)
oauth_nonce = OauthNonce.create(:nonce => nonce, :timestamp => timestamp)
return false if Time.now.to_i - timestamp.to_i > 86400
oauth_nonce = OauthNonce.create(:nonce => nonce, :timestamp => timestamp.to_i)
return false if oauth_nonce.new_record?
oauth_nonce
end

View file

@ -15,7 +15,7 @@ class Redaction < ActiveRecord::Base
has_many :old_relations
validates :description, :presence => true
validates :description_format, :inclusion => { :in => %w(text html markdown) }
validates :description_format, :inclusion => { :in => %w[text html markdown] }
# this method overrides the AR default to provide the rich
# text object for the description field.

View file

@ -33,10 +33,10 @@ class Relation < ActiveRecord::Base
scope :ways, ->(*ids) { joins(:relation_members).where(:current_relation_members => { :member_type => "Way", :member_id => ids.flatten }) }
scope :relations, ->(*ids) { joins(:relation_members).where(:current_relation_members => { :member_type => "Relation", :member_id => ids.flatten }) }
TYPES = %w(node way relation).freeze
TYPES = %w[node way relation].freeze
def self.from_xml(xml, create = false)
p = XML::Parser.string(xml)
p = XML::Parser.string(xml, :options => XML::Parser::Options::NOERROR)
doc = p.parse
doc.find("//osm/relation").each do |pt|
@ -60,7 +60,7 @@ class Relation < ActiveRecord::Base
relation.id = pt["id"].to_i
# .to_i will return 0 if there is no number that can be parsed.
# We want to make sure that there is no id with zero anyway
raise OSM::APIBadUserInput.new("ID of relation cannot be zero when updating.") if relation.id == 0
raise OSM::APIBadUserInput.new("ID of relation cannot be zero when updating.") if relation.id.zero?
end
# We don't care about the timestamp nor the visibility as these are either
@ -281,15 +281,19 @@ class Relation < ActiveRecord::Base
private
def save_with_history!
t = Time.now.getutc
self.version += 1
self.timestamp = t
Relation.transaction do
# have to be a little bit clever here - to detect if any tags
# changed then we have to monitor their before and after state.
tags_changed = false
t = Time.now.getutc
self.version += 1
self.timestamp = t
save!
# clone the object before saving it so that the original is
# still marked as dirty if we retry the transaction
clone.save!
tags = self.tags.clone
relation_tags.each do |old_tag|
@ -313,7 +317,7 @@ class Relation < ActiveRecord::Base
# if there are left-over tags then they are new and will have to
# be added.
tags_changed |= !tags.empty?
RelationTag.delete_all(:relation_id => id)
RelationTag.where(:relation_id => id).delete_all
self.tags.each do |k, v|
tag = RelationTag.new
tag.relation_id = id
@ -343,7 +347,7 @@ 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(:relation_id => id)
RelationMember.where(:relation_id => id).delete_all
members.each_with_index do |m, i|
mem = RelationMember.new
mem.relation_id = id
@ -370,7 +374,7 @@ class Relation < ActiveRecord::Base
# materially change the rest of the relation.
any_relations =
changed_members.collect { |_id, type| type == "relation" }
.inject(false) { |a, e| a || e }
.inject(false) { |acc, elem| acc || elem }
update_members = if tags_changed || any_relations
# add all non-relation bounding boxes to the changeset

View file

@ -7,14 +7,14 @@ class Trace < ActiveRecord::Base
scope :visible, -> { where(:visible => true) }
scope :visible_to, ->(u) { visible.where("visibility IN ('public', 'identifiable') OR user_id = ?", u) }
scope :visible_to_all, -> { where(:visibility => %w(public identifiable)) }
scope :visible_to_all, -> { where(:visibility => %w[public identifiable]) }
scope :tagged, ->(t) { joins(:tags).where(:gpx_file_tags => { :tag => t }) }
validates :user, :presence => true, :associated => true
validates :name, :presence => true, :length => 1..255
validates :description, :presence => { :on => :create }, :length => 1..255
validates :timestamp, :presence => true
validates :visibility, :inclusion => %w(private public trackable identifiable)
validates :visibility, :inclusion => %w[private public trackable identifiable]
def destroy
super
@ -29,7 +29,7 @@ class Trace < ActiveRecord::Base
def tagstring=(s)
self.tags = if s.include? ","
s.split(/\s*,\s*/).select { |tag| tag !~ /^\s*$/ }.collect do |tag|
s.split(/\s*,\s*/).reject { |tag| tag =~ /^\s*$/ }.collect do |tag|
tt = Tracetag.new
tt.tag = tag
tt
@ -95,7 +95,7 @@ class Trace < ActiveRecord::Base
end
def mime_type
filetype = `/usr/bin/file -bz #{trace_name}`.chomp
filetype = `/usr/bin/file -Lbz #{trace_name}`.chomp
gzipped = filetype =~ /gzip compressed/
bzipped = filetype =~ /bzip2 compressed/
zipped = filetype =~ /Zip archive/
@ -117,7 +117,7 @@ class Trace < ActiveRecord::Base
end
def extension_name
filetype = `/usr/bin/file -bz #{trace_name}`.chomp
filetype = `/usr/bin/file -Lbz #{trace_name}`.chomp
gzipped = filetype =~ /gzip compressed/
bzipped = filetype =~ /bzip2 compressed/
zipped = filetype =~ /Zip archive/
@ -174,7 +174,7 @@ class Trace < ActiveRecord::Base
# Read in xml as text and return it's Node object representation
def self.from_xml(xml, create = false)
p = XML::Parser.string(xml)
p = XML::Parser.string(xml, :options => XML::Parser::Options::NOERROR)
doc = p.parse
doc.find("//osm/gpx_file").each do |pt|
@ -197,7 +197,7 @@ class Trace < ActiveRecord::Base
trace.id = pt["id"].to_i
# .to_i will return 0 if there is no number that can be parsed.
# We want to make sure that there is no id with zero anyway
raise OSM::APIBadUserInput.new("ID of trace cannot be zero when updating.") if trace.id == 0
raise OSM::APIBadUserInput.new("ID of trace cannot be zero when updating.") if trace.id.zero?
end
# We don't care about the time, as it is explicitly set on create/update/delete
@ -218,7 +218,7 @@ class Trace < ActiveRecord::Base
def xml_file
# TODO: *nix specific, could do to work on windows... would be functionally inferior though - check for '.gz'
filetype = `/usr/bin/file -bz #{trace_name}`.chomp
filetype = `/usr/bin/file -Lbz #{trace_name}`.chomp
gzipped = filetype =~ /gzip compressed/
bzipped = filetype =~ /bzip2 compressed/
zipped = filetype =~ /Zip archive/
@ -261,7 +261,7 @@ class Trace < ActiveRecord::Base
first = true
# If there are any existing points for this trace then delete them
Tracepoint.delete_all(:gpx_id => id)
Tracepoint.where(:gpx_id => id).delete_all
gpx.points do |point|
if first

View file

@ -4,10 +4,12 @@ class User < ActiveRecord::Base
has_many :traces, -> { where(:visible => true) }
has_many :diary_entries, -> { order(:created_at => :desc) }
has_many :diary_comments, -> { order(:created_at => :desc) }
has_many :diary_entry_subscriptions, :class_name => "DiaryEntrySubscription"
has_many :diary_subscriptions, :through => :diary_entry_subscriptions, :source => :diary_entry
has_many :messages, -> { where(:to_user_visible => true).order(:sent_on => :desc).preload(:sender, :recipient) }, :foreign_key => :to_user_id
has_many :new_messages, -> { where(:to_user_visible => true, :message_read => false).order(:sent_on => :desc) }, :class_name => "Message", :foreign_key => :to_user_id
has_many :sent_messages, -> { where(:from_user_visible => true).order(:sent_on => :desc).preload(:sender, :recipient) }, :class_name => "Message", :foreign_key => :from_user_id
has_many :friends, -> { joins(:befriendee).where(:users => { :status => %w(active confirmed) }) }
has_many :friends, -> { joins(:befriendee).where(:users => { :status => %w[active confirmed] }) }
has_many :friend_users, :through => :friends, :source => :befriendee
has_many :tokens, :class_name => "UserToken"
has_many :preferences, :class_name => "UserPreference"
@ -32,8 +34,8 @@ class User < ActiveRecord::Base
has_many :reports
scope :visible, -> { where(:status => %w(pending active confirmed)) }
scope :active, -> { where(:status => %w(active confirmed)) }
scope :visible, -> { where(:status => %w[pending active confirmed]) }
scope :active, -> { where(:status => %w[active confirmed]) }
scope :identifiable, -> { where(:data_public => true) }
has_attached_file :image,
@ -41,7 +43,7 @@ class User < ActiveRecord::Base
:styles => { :large => "100x100>", :small => "50x50>" }
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)
: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? },
@ -87,7 +89,7 @@ class User < ActiveRecord::Base
user = nil
end
elsif options[:token]
token = UserToken.find_by_token(options[:token])
token = UserToken.find_by(:token => options[:token])
user = token.user if token
end
@ -98,7 +100,7 @@ class User < ActiveRecord::Base
user = nil
end
token.update_column(:expiry, 1.week.from_now) if token && user
token.update(:expiry => 1.week.from_now) if token && user
user
end
@ -165,13 +167,13 @@ class User < ActiveRecord::Base
##
# returns true if a user is visible
def visible?
%w(pending active confirmed).include? status
%w[pending active confirmed].include? status
end
##
# returns true if a user is active
def active?
%w(active confirmed).include? status
%w[active confirmed].include? status
end
##
@ -220,8 +222,8 @@ class User < ActiveRecord::Base
def spam_score
changeset_score = changesets.size * 50
trace_score = traces.size * 50
diary_entry_score = diary_entries.inject(0) { |a, e| a + e.body.spam_score }
diary_comment_score = diary_comments.inject(0) { |a, e| a + e.body.spam_score }
diary_entry_score = diary_entries.inject(0) { |acc, elem| acc + elem.body.spam_score }
diary_comment_score = diary_comments.inject(0) { |acc, elem| acc + elem.body.spam_score }
score = description.spam_score / 4.0
score += diary_entries.where("created_at > ?", 1.day.ago).count * 10
@ -237,14 +239,14 @@ class User < ActiveRecord::Base
# perform a spam check on a user
def spam_check
if status == "active" && spam_score > SPAM_THRESHOLD
update_column(:status, "suspended")
update(:status => "suspended")
end
end
##
# return an oauth access token for a specified application
def access_token(application_key)
ClientApplication.find_by_key(application_key).access_token_for_user(self)
ClientApplication.find_by(:key => application_key).access_token_for_user(self)
end
private

View file

@ -26,6 +26,13 @@ class UserBlock < ActiveRecord::Base
needs_view || ends_at > Time.now.getutc
end
##
# returns true if the block is a "zero hour" block
def zero_hour?
# if the times differ more than 1 minute we probably have more important issues
needs_view && (ends_at.to_i - updated_at.to_i) < 60
end
##
# revokes the block, allowing the user to use the API again. the argument
# is the user object who is revoking the ban.

View file

@ -1,7 +1,8 @@
class UserRole < ActiveRecord::Base
belongs_to :user
belongs_to :granter, :class_name => "User"
ALL_ROLES = %w(administrator moderator).freeze
ALL_ROLES = %w[administrator moderator].freeze
validates :role, :inclusion => ALL_ROLES, :uniqueness => { :scope => :user_id }
end

View file

@ -34,7 +34,7 @@ class Way < ActiveRecord::Base
# Read in xml as text and return it's Way object representation
def self.from_xml(xml, create = false)
p = XML::Parser.string(xml)
p = XML::Parser.string(xml, :options => XML::Parser::Options::NOERROR)
doc = p.parse
doc.find("//osm/way").each do |pt|
@ -58,7 +58,7 @@ class Way < ActiveRecord::Base
way.id = pt["id"].to_i
# .to_i will return 0 if there is no number that can be parsed.
# We want to make sure that there is no id with zero anyway
raise OSM::APIBadUserInput.new("ID of way cannot be zero when updating.") if way.id == 0
raise OSM::APIBadUserInput.new("ID of way cannot be zero when updating.") if way.id.zero?
end
# We don't care about the timestamp nor the visibility as these are either
@ -222,7 +222,7 @@ class Way < ActiveRecord::Base
lock!
check_consistency(self, new_way, user)
rels = Relation.joins(:relation_members).where(:visible => true, :current_relation_members => { :member_type => "Way", :member_id => id }).order(:id)
raise OSM::APIPreconditionFailedError.new("Way #{id} is still used by relations #{rels.collect(&:id).join(",")}.") unless rels.empty?
raise OSM::APIPreconditionFailedError.new("Way #{id} is still used by relations #{rels.collect(&:id).join(',')}.") unless rels.empty?
self.changeset_id = new_way.changeset_id
self.changeset = new_way.changeset
@ -255,6 +255,9 @@ class Way < ActiveRecord::Base
def save_with_history!
t = Time.now.getutc
self.version += 1
self.timestamp = t
# update the bounding box, note that this has to be done both before
# and after the save, so that nodes from both versions are included in the
# bbox. we use a copy of the changeset so that it isn't reloaded
@ -263,12 +266,12 @@ class Way < ActiveRecord::Base
cs.update_bbox!(bbox) unless nodes.empty?
Way.transaction do
self.version += 1
self.timestamp = t
save!
# clone the object before saving it so that the original is
# still marked as dirty if we retry the transaction
clone.save!
tags = self.tags
WayTag.delete_all(:way_id => id)
WayTag.where(:way_id => id).delete_all
tags.each do |k, v|
tag = WayTag.new
tag.way_id = id
@ -278,7 +281,7 @@ class Way < ActiveRecord::Base
end
nds = self.nds
WayNode.delete_all(:way_id => id)
WayNode.where(:way_id => id).delete_all
sequence = 1
nds.each do |n|
nd = WayNode.new

View file

@ -1,6 +1,6 @@
# create list of permissions
xml.instruct! :xml, :version=>"1.0"
xml.osm("version" => "#{API_VERSION}", "generator" => "OpenStreetMap Server") do
xml.instruct! :xml, :version => "1.0"
xml.osm("version" => API_VERSION.to_s, "generator" => "OpenStreetMap Server") do
xml.permissions do
@permissions.each do |permission|
xml.permission :name => permission

View file

@ -10,14 +10,14 @@
<div class='browse-section browse-relation'>
<%= render :partial => "common_details", :object => relation %>
<% unless relation.relation_members.empty? %>
<h4><%= t'browse.relation.members' %></h4>
<ul><%= render :partial => "relation_member", :collection => relation.relation_members %></ul>
<% end %>
<% unless relation.containing_relation_members.empty? %>
<h4><%= t'browse.part_of' %></h4>
<ul><%= render :partial => "containing_relation", :collection => relation.containing_relation_members.uniq %></ul>
<% end %>
<% unless relation.relation_members.empty? %>
<h4><%= t'browse.relation.members' %></h4>
<ul><%= render :partial => "relation_member", :collection => relation.relation_members %></ul>
<% end %>
</div>
<% end %>

View file

@ -10,6 +10,13 @@
<div class='browse-section browse-way'>
<%= render :partial => "common_details", :object => way %>
<% unless way.containing_relation_members.empty? %>
<h4><%= t'browse.part_of' %></h4>
<ul>
<%= render :partial => "containing_relation", :collection => way.containing_relation_members.uniq %>
</ul>
<% end %>
<% unless way.way_nodes.empty? %>
<h4><%= t'browse.way.nodes' %></h4>
<ul>
@ -24,12 +31,5 @@
<% end %>
</ul>
<% end %>
<% unless way.containing_relation_members.empty? %>
<h4><%= t'browse.part_of' %></h4>
<ul>
<%= render :partial => "containing_relation", :collection => way.containing_relation_members.uniq %>
</ul>
<% end %>
</div>
<% end %>

Some files were not shown because too many files have changed in this diff Show more