]> git.openstreetmap.org Git - rails.git/commitdiff
Merge remote-tracking branch 'upstream/pull/5459'
authorTom Hughes <tom@compton.nu>
Tue, 7 Jan 2025 19:08:13 +0000 (19:08 +0000)
committerTom Hughes <tom@compton.nu>
Tue, 7 Jan 2025 19:08:13 +0000 (19:08 +0000)
61 files changed:
Gemfile.lock
app/abilities/ability.rb
app/assets/javascripts/index/changeset.js
app/assets/javascripts/index/history.js
app/assets/javascripts/leaflet.map.js
app/controllers/accounts/deletions_controller.rb [moved from app/controllers/account/deletions_controller.rb with 92% similarity]
app/controllers/application_controller.rb
app/controllers/diary_comments_controller.rb
app/controllers/elements_controller.rb [new file with mode: 0644]
app/controllers/messages/replies_controller.rb [new file with mode: 0644]
app/controllers/messages_controller.rb
app/controllers/nodes_controller.rb
app/controllers/old_elements_controller.rb [new file with mode: 0644]
app/controllers/old_nodes_controller.rb
app/controllers/old_relations_controller.rb
app/controllers/old_ways_controller.rb
app/controllers/relations_controller.rb
app/controllers/ways_controller.rb
app/helpers/changesets_helper.rb
app/helpers/user_blocks_helper.rb
app/mailers/user_mailer.rb
app/views/accounts/deletions/show.html.erb [moved from app/views/account/deletions/show.html.erb with 100% similarity]
app/views/accounts/edit.html.erb
app/views/application/_auth_providers.html.erb
app/views/browse/not_found.html.erb
app/views/changesets/_changeset.html.erb
app/views/changesets/_not_found_message.html.erb [new file with mode: 0644]
app/views/changesets/show.html.erb
app/views/elements/show.html.erb [moved from app/views/browse/feature.html.erb with 100% similarity]
app/views/messages/show.html.erb
app/views/nodes/_not_found_message.html.erb [new file with mode: 0644]
app/views/notes/_not_found_message.html.erb [new file with mode: 0644]
app/views/old_elements/_actions.html.erb [moved from app/views/browse/_version_actions.erb with 87% similarity]
app/views/old_elements/index.html.erb [moved from app/views/browse/history.html.erb with 72% similarity]
app/views/old_nodes/_not_found_message.html.erb [new file with mode: 0644]
app/views/old_nodes/not_found.html.erb [deleted file]
app/views/old_nodes/show.html.erb
app/views/old_relations/_not_found_message.html.erb [new file with mode: 0644]
app/views/old_relations/not_found.html.erb [deleted file]
app/views/old_relations/show.html.erb
app/views/old_ways/_not_found_message.html.erb [new file with mode: 0644]
app/views/old_ways/not_found.html.erb [deleted file]
app/views/old_ways/show.html.erb
app/views/relations/_not_found_message.html.erb [new file with mode: 0644]
app/views/ways/_not_found_message.html.erb [new file with mode: 0644]
config/locales/en.yml
config/routes.rb
lib/auth.rb
test/controllers/diary_comments_controller_test.rb
test/controllers/messages/replies_controller_test.rb [new file with mode: 0644]
test/controllers/messages_controller_test.rb
test/controllers/nodes_controller_test.rb
test/controllers/old_nodes_controller_test.rb
test/controllers/old_relations_controller_test.rb
test/controllers/old_ways_controller_test.rb
test/controllers/relations_controller_test.rb
test/controllers/users_controller_test.rb
test/controllers/ways_controller_test.rb
test/helpers/user_blocks_helper_test.rb
test/system/browse_test.rb [new file with mode: 0644]
vendor/assets/leaflet/leaflet.osm.js

index 02b1777906596658b49112eabfe646520d31ec29..5c10d3de3e7d4d04986bf34d4317862497f9d913 100644 (file)
@@ -92,7 +92,7 @@ GEM
     autoprefixer-rails (10.4.19.0)
       execjs (~> 2)
     aws-eventstream (1.3.0)
-    aws-partitions (1.1029.0)
+    aws-partitions (1.1032.0)
     aws-sdk-core (3.214.1)
       aws-eventstream (~> 1, >= 1.3.0)
       aws-partitions (~> 1, >= 1.992.0)
@@ -101,7 +101,7 @@ GEM
     aws-sdk-kms (1.96.0)
       aws-sdk-core (~> 3, >= 3.210.0)
       aws-sigv4 (~> 1.5)
-    aws-sdk-s3 (1.176.1)
+    aws-sdk-s3 (1.177.0)
       aws-sdk-core (~> 3, >= 3.210.0)
       aws-sdk-kms (~> 1)
       aws-sigv4 (~> 1.5)
@@ -216,41 +216,42 @@ GEM
       doorkeeper (>= 5.5, < 5.9)
       jwt (>= 2.5)
     drb (2.2.1)
-    dry-configurable (1.2.0)
-      dry-core (~> 1.0, < 2)
+    dry-configurable (1.3.0)
+      dry-core (~> 1.1)
       zeitwerk (~> 2.6)
-    dry-core (1.0.2)
+    dry-core (1.1.0)
       concurrent-ruby (~> 1.0)
       logger
       zeitwerk (~> 2.6)
-    dry-inflector (1.1.0)
-    dry-initializer (3.1.1)
-    dry-logic (1.5.0)
+    dry-inflector (1.2.0)
+    dry-initializer (3.2.0)
+    dry-logic (1.6.0)
+      bigdecimal
       concurrent-ruby (~> 1.0)
-      dry-core (~> 1.0, < 2)
+      dry-core (~> 1.1)
       zeitwerk (~> 2.6)
-    dry-schema (1.13.4)
+    dry-schema (1.14.0)
       concurrent-ruby (~> 1.0)
       dry-configurable (~> 1.0, >= 1.0.1)
-      dry-core (~> 1.0, < 2)
-      dry-initializer (~> 3.0)
-      dry-logic (>= 1.4, < 2)
-      dry-types (>= 1.7, < 2)
+      dry-core (~> 1.1)
+      dry-initializer (~> 3.2)
+      dry-logic (~> 1.5)
+      dry-types (~> 1.8)
       zeitwerk (~> 2.6)
-    dry-types (1.7.2)
+    dry-types (1.8.0)
       bigdecimal (~> 3.0)
       concurrent-ruby (~> 1.0)
       dry-core (~> 1.0)
       dry-inflector (~> 1.0)
       dry-logic (~> 1.4)
       zeitwerk (~> 2.6)
-    dry-validation (1.10.0)
+    dry-validation (1.11.0)
       concurrent-ruby (~> 1.0)
-      dry-core (~> 1.0, < 2)
-      dry-initializer (~> 3.0)
-      dry-schema (>= 1.12, < 2)
+      dry-core (~> 1.1)
+      dry-initializer (~> 3.2)
+      dry-schema (~> 1.14)
       zeitwerk (~> 2.6)
-    erb_lint (0.7.0)
+    erb_lint (0.8.0)
       activesupport
       better_html (>= 2.0.1)
       parser (>= 2.7.1.4)
@@ -293,7 +294,7 @@ GEM
     google-protobuf (3.25.5)
     hashdiff (1.1.2)
     hashie (5.0.0)
-    highline (3.1.1)
+    highline (3.1.2)
       reline
     htmlentities (4.3.4)
     http_accept_language (2.1.1)
@@ -357,7 +358,7 @@ GEM
     logstasher (2.1.5)
       activesupport (>= 5.2)
       request_store
-    loofah (2.23.1)
+    loofah (2.24.0)
       crass (~> 1.0.2)
       nokogiri (>= 1.12.0)
     mail (2.8.1)
@@ -383,7 +384,7 @@ GEM
     nap (1.1.0)
     net-http (0.6.0)
       uri
-    net-imap (0.5.4)
+    net-imap (0.5.5)
       date
       net-protocol
     net-pop (0.1.2)
@@ -531,7 +532,7 @@ GEM
     rb-fsevent (0.11.2)
     rb-inotify (0.11.1)
       ffi (~> 1.0)
-    rchardet (1.8.0)
+    rchardet (1.9.0)
     rdoc (6.10.0)
       psych (>= 4.0.0)
     regexp_parser (2.10.0)
@@ -564,7 +565,7 @@ GEM
     rubocop-minitest (0.36.0)
       rubocop (>= 1.61, < 2.0)
       rubocop-ast (>= 1.31.1, < 2.0)
-    rubocop-performance (1.23.0)
+    rubocop-performance (1.23.1)
       rubocop (>= 1.48.1, < 2.0)
       rubocop-ast (>= 1.31.1, < 2.0)
     rubocop-rails (2.28.0)
@@ -579,7 +580,7 @@ GEM
     ruby-vips (2.2.2)
       ffi (~> 1.12)
       logger
-    rubyzip (2.3.2)
+    rubyzip (2.4.1)
     sanitize (7.0.0)
       crass (~> 1.0.2)
       nokogiri (>= 1.16.8)
@@ -651,7 +652,8 @@ GEM
       hashdiff (>= 0.4.0, < 2.0.0)
     webrick (1.9.1)
     websocket (1.2.11)
-    websocket-driver (0.7.6)
+    websocket-driver (0.7.7)
+      base64
       websocket-extensions (>= 0.1.0)
     websocket-extensions (0.1.5)
     xpath (3.2.0)
index 6638016d72ea55b1cad4fbd908228562d1db00fc..7ed6470b84e5830c37e4184e50743b9d8a96ee8b 100644 (file)
@@ -42,7 +42,7 @@ class Ability
         can :update, DiaryEntry, :user => user
         can [:create], DiaryComment
         can [:make_friend, :remove_friend], Friendship
-        can [:read, :create, :reply, :inbox, :outbox, :muted, :mark, :unmute, :destroy], Message
+        can [:read, :create, :mark, :unmute, :destroy], Message
         can [:close, :reopen], Note
         can [:read, :update], :preference
         can :update, :profile
index 75a1f7b4dfa770463867cf7fafafbaf05babb1e3..caf40f6b6e7322ce5923e3f8b201a6a41ac73d42 100644 (file)
@@ -1,30 +1,26 @@
 OSM.Changeset = function (map) {
   var page = {},
-      content = $("#sidebar_content"),
-      currentChangesetId;
+      content = $("#sidebar_content");
 
-  page.pushstate = page.popstate = function (path, id) {
+  page.pushstate = page.popstate = function (path) {
     OSM.loadSidebarContent(path, function () {
-      page.load(path, id);
+      page.load();
     });
   };
 
-  page.load = function (path, id) {
-    if (id) currentChangesetId = id;
-    initialize();
-    addChangeset(currentChangesetId, true);
-  };
+  page.load = function () {
+    const changesetData = content.find("[data-changeset]").data("changeset");
+    changesetData.type = "changeset";
 
-  function addChangeset(id, center) {
-    map.addObject({ type: "changeset", id: parseInt(id, 10) }, function (bounds) {
-      if (!window.location.hash && bounds.isValid() &&
-          (center || !map.getBounds().contains(bounds))) {
+    initialize();
+    map.addObject(changesetData, function (bounds) {
+      if (!window.location.hash && bounds.isValid()) {
         OSM.router.withoutMoveListener(function () {
           map.fitBounds(bounds);
         });
       }
     });
-  }
+  };
 
   function updateChangeset(method, url, include_data) {
     var data;
index c6ba0c2edc9831853eedfec9f533531d71d5f341..ae8f027ed8727586f2b48d317f473f6fc8f1fe67 100644 (file)
@@ -164,6 +164,7 @@ OSM.History = function (map) {
   page.unload = function () {
     map.removeLayer(group);
     map.off("moveend", update);
+    map.off("zoomend", updateBounds);
   };
 
   return page;
index 6537b0b233568ada1988c56d6c215789864a8f30..e0c2ee60b47fb0ddd5251ac520b3c8e234f8ebca 100644 (file)
@@ -267,7 +267,7 @@ L.OSM.Map = L.Map.extend({
 
     this.removeObject();
 
-    if (object.type === "note") {
+    if (object.type === "note" || object.type === "changeset") {
       this._objectLoader = {
         abort: function () {}
       };
@@ -275,18 +275,27 @@ L.OSM.Map = L.Map.extend({
       this._object = object;
       this._objectLayer = L.featureGroup().addTo(this);
 
-      L.circleMarker(object.latLng, haloStyle).addTo(this._objectLayer);
+      if (object.type === "note") {
+        L.circleMarker(object.latLng, haloStyle).addTo(this._objectLayer);
 
-      if (object.icon) {
-        L.marker(object.latLng, {
-          icon: object.icon,
-          opacity: 1,
-          interactive: true
-        }).addTo(this._objectLayer);
+        if (object.icon) {
+          L.marker(object.latLng, {
+            icon: object.icon,
+            opacity: 1,
+            interactive: true
+          }).addTo(this._objectLayer);
+        }
+      } else if (object.type === "changeset") {
+        if (object.bbox) {
+          L.rectangle([
+            [object.bbox.minlat, object.bbox.minlon],
+            [object.bbox.maxlat, object.bbox.maxlon]
+          ], changesetStyle).addTo(this._objectLayer);
+        }
       }
 
       if (callback) callback(this._objectLayer.getBounds());
-    } else { // element or changeset handled by L.OSM.DataLayer
+    } else { // element handled by L.OSM.DataLayer
       var map = this;
       this._objectLoader = $.ajax({
         url: OSM.apiUrl(object),
@@ -303,13 +312,11 @@ L.OSM.Map = L.Map.extend({
             }
           });
 
-          map._objectLayer.interestingNode = function (node, ways, relations) {
+          map._objectLayer.interestingNode = function (node, wayNodes, relationNodes) {
             if (object.type === "node") {
               return true;
             } else if (object.type === "relation") {
-              for (var i = 0; i < relations.length; i++) {
-                if (relations[i].members.indexOf(node) !== -1) return true;
-              }
+              return Boolean(relationNodes[node.id]);
             } else {
               return false;
             }
similarity index 92%
rename from app/controllers/account/deletions_controller.rb
rename to app/controllers/accounts/deletions_controller.rb
index 2e3c777fa362b7cd4a3070215715468e14c6388e..303da6cfb5d0d9bb9f0e7b1dde499a084d79abe5 100644 (file)
@@ -1,4 +1,4 @@
-module Account
+module Accounts
   class DeletionsController < ApplicationController
     layout "site"
 
index 32b53bad71c3f431d79234d65e354f6cafcf13c9..1ef49bf4629c209a6e14a61c3fc97656c5405420 100644 (file)
@@ -20,7 +20,7 @@ class ApplicationController < ActionController::Base
   helper_method :oauth_token
 
   def self.allow_thirdparty_images(**options)
-    content_security_policy(options) do |policy|
+    content_security_policy(**options) do |policy|
       policy.img_src("*", :data)
     end
   end
index f6597cf4c0fac1f74fa69a2c12b9851fdc6ab4ad..676bc22a66a10306f1fc8c5f7628d40c5e7baee5 100644 (file)
@@ -13,7 +13,7 @@ class DiaryCommentsController < ApplicationController
   before_action :lookup_user, :only => :index
   before_action :check_database_writable, :only => [:create, :hide, :unhide]
 
-  allow_thirdparty_images :only => :index
+  allow_thirdparty_images :only => [:index, :create]
 
   def index
     @title = t ".title", :user => @user.display_name
diff --git a/app/controllers/elements_controller.rb b/app/controllers/elements_controller.rb
new file mode 100644 (file)
index 0000000..99c8afe
--- /dev/null
@@ -0,0 +1,12 @@
+class ElementsController < ApplicationController
+  layout :map_layout
+
+  before_action :authorize_web
+  before_action :set_locale
+  before_action -> { check_database_readable(:need_api => true) }
+  before_action :require_oauth
+
+  authorize_resource
+
+  around_action :web_timeout
+end
diff --git a/app/controllers/messages/replies_controller.rb b/app/controllers/messages/replies_controller.rb
new file mode 100644 (file)
index 0000000..b1e7b8d
--- /dev/null
@@ -0,0 +1,50 @@
+module Messages
+  class RepliesController < ApplicationController
+    layout "site"
+
+    before_action :authorize_web
+    before_action :set_locale
+
+    authorize_resource :class => Message
+
+    before_action :check_database_readable
+    before_action :check_database_writable
+
+    allow_thirdparty_images
+
+    # Allow the user to reply to another message.
+    def new
+      message = Message.find(params[:message_id])
+
+      if message.recipient == current_user
+        message.update(:message_read => true)
+
+        @message = Message.new(
+          :recipient => message.sender,
+          :title => "Re: #{message.title.sub(/^Re:\s*/, '')}",
+          :body => "On #{message.sent_on} #{message.sender.display_name} wrote:\n\n#{message.body.gsub(/^/, '> ')}"
+        )
+
+        @title = @message.title
+
+        render "messages/new"
+      elsif message.sender == current_user
+        @message = Message.new(
+          :recipient => message.recipient,
+          :title => "Re: #{message.title.sub(/^Re:\s*/, '')}",
+          :body => "On #{message.sent_on} #{message.sender.display_name} wrote:\n\n#{message.body.gsub(/^/, '> ')}"
+        )
+
+        @title = @message.title
+
+        render "messages/new"
+      else
+        flash[:notice] = t ".wrong_user", :user => current_user.display_name
+        redirect_to login_path(:referer => request.fullpath)
+      end
+    rescue ActiveRecord::RecordNotFound
+      @title = t "messages.no_such_message.title"
+      render "messages/no_such_message", :status => :not_found
+    end
+  end
+end
index 7162b900a011c4719c18a212f96691d3e68e26b8..cc5f6c56d19dd4a6481534bc082eace36fa403ef 100644 (file)
@@ -10,7 +10,7 @@ class MessagesController < ApplicationController
 
   before_action :lookup_user, :only => [:new, :create]
   before_action :check_database_readable
-  before_action :check_database_writable, :only => [:new, :create, :reply, :mark, :destroy]
+  before_action :check_database_writable, :only => [:new, :create, :mark, :destroy]
 
   allow_thirdparty_images :only => [:new, :create, :show]
 
@@ -49,7 +49,7 @@ class MessagesController < ApplicationController
     elsif @message.save
       flash[:notice] = t ".message_sent"
       UserMailer.message_notification(@message).deliver_later if @message.notify_recipient?
-      redirect_to messages_inbox_path
+      redirect_to messages_outbox_path
     else
       @title = t "messages.new.title"
       render :action => "new"
@@ -73,41 +73,6 @@ class MessagesController < ApplicationController
     render :action => "no_such_message", :status => :not_found
   end
 
-  # Allow the user to reply to another message.
-  def reply
-    message = Message.find(params[:message_id])
-
-    if message.recipient == current_user
-      message.update(:message_read => true)
-
-      @message = Message.new(
-        :recipient => message.sender,
-        :title => "Re: #{message.title.sub(/^Re:\s*/, '')}",
-        :body => "On #{message.sent_on} #{message.sender.display_name} wrote:\n\n#{message.body.gsub(/^/, '> ')}"
-      )
-
-      @title = @message.title
-
-      render :action => "new"
-    elsif message.sender == current_user
-      @message = Message.new(
-        :recipient => message.recipient,
-        :title => "Re: #{message.title.sub(/^Re:\s*/, '')}",
-        :body => "On #{message.sent_on} #{message.sender.display_name} wrote:\n\n#{message.body.gsub(/^/, '> ')}"
-      )
-
-      @title = @message.title
-
-      render :action => "new"
-    else
-      flash[:notice] = t ".wrong_user", :user => current_user.display_name
-      redirect_to login_path(:referer => request.fullpath)
-    end
-  rescue ActiveRecord::RecordNotFound
-    @title = t "messages.no_such_message.title"
-    render :action => "no_such_message", :status => :not_found
-  end
-
   # Set the message as being read or unread.
   def mark
     @message = current_user.messages.unscope(:where => :muted).find(params[:message_id])
index a05fa8cd2455ced0d35476e6502f3e4c0557f6a5..0ef07dbbfc689772637c4fdffc3e2affc31802d0 100644 (file)
@@ -1,19 +1,7 @@
-class NodesController < ApplicationController
-  layout :map_layout
-
-  before_action :authorize_web
-  before_action :set_locale
-  before_action -> { check_database_readable(:need_api => true) }
-  before_action :require_oauth
-
-  authorize_resource
-
-  around_action :web_timeout
-
+class NodesController < ElementsController
   def show
     @type = "node"
     @feature = Node.preload(:node_tags, :containing_relation_members, :changeset => [:changeset_tags, :user], :ways => :way_tags).find(params[:id])
-    render "browse/feature"
   rescue ActiveRecord::RecordNotFound
     render "browse/not_found", :status => :not_found
   end
diff --git a/app/controllers/old_elements_controller.rb b/app/controllers/old_elements_controller.rb
new file mode 100644 (file)
index 0000000..02c999b
--- /dev/null
@@ -0,0 +1,19 @@
+class OldElementsController < ApplicationController
+  layout :map_layout
+
+  before_action :authorize_web
+  before_action :set_locale
+  before_action -> { check_database_readable(:need_api => true) }
+  before_action :require_oauth
+
+  authorize_resource
+
+  before_action :require_moderator_for_unredacted_history
+  around_action :web_timeout
+
+  private
+
+  def require_moderator_for_unredacted_history
+    deny_access(nil) if params[:show_redactions] && !current_user&.moderator?
+  end
+end
index 596b579673649c4bcd806c628dd8a8218a8344ed..3b187e4abff31d2d3c74574b9839073777a5b25d 100644 (file)
@@ -1,20 +1,7 @@
-class OldNodesController < ApplicationController
-  layout :map_layout
-
-  before_action :authorize_web
-  before_action :set_locale
-  before_action -> { check_database_readable(:need_api => true) }
-  before_action :require_oauth
-
-  authorize_resource
-
-  before_action :require_moderator_for_unredacted_history
-  around_action :web_timeout
-
+class OldNodesController < OldElementsController
   def index
     @type = "node"
     @feature = Node.preload(:node_tags, :old_nodes => [:old_tags, { :changeset => [:changeset_tags, :user] }]).find(params[:id])
-    render "browse/history"
   rescue ActiveRecord::RecordNotFound
     render "browse/not_found", :status => :not_found
   end
@@ -23,12 +10,6 @@ class OldNodesController < ApplicationController
     @type = "node"
     @feature = OldNode.preload(:old_tags, :changeset => [:changeset_tags, :user]).find([params[:id], params[:version]])
   rescue ActiveRecord::RecordNotFound
-    render :action => "not_found", :status => :not_found
-  end
-
-  private
-
-  def require_moderator_for_unredacted_history
-    deny_access(nil) if params[:show_redactions] && !current_user&.moderator?
+    render "browse/not_found", :status => :not_found
   end
 end
index d57cf25fe070dc3d3a278650ede0c2d049c67e89..ec256d6af680caaf10b39f4b20c453d1885b16da 100644 (file)
@@ -1,20 +1,7 @@
-class OldRelationsController < ApplicationController
-  layout :map_layout
-
-  before_action :authorize_web
-  before_action :set_locale
-  before_action -> { check_database_readable(:need_api => true) }
-  before_action :require_oauth
-
-  authorize_resource
-
-  before_action :require_moderator_for_unredacted_history
-  around_action :web_timeout
-
+class OldRelationsController < OldElementsController
   def index
     @type = "relation"
     @feature = Relation.preload(:relation_tags, :old_relations => [:old_tags, { :changeset => [:changeset_tags, :user], :old_members => :member }]).find(params[:id])
-    render "browse/history"
   rescue ActiveRecord::RecordNotFound
     render "browse/not_found", :status => :not_found
   end
@@ -23,12 +10,6 @@ class OldRelationsController < ApplicationController
     @type = "relation"
     @feature = OldRelation.preload(:old_tags, :changeset => [:changeset_tags, :user], :old_members => :member).find([params[:id], params[:version]])
   rescue ActiveRecord::RecordNotFound
-    render :action => "not_found", :status => :not_found
-  end
-
-  private
-
-  def require_moderator_for_unredacted_history
-    deny_access(nil) if params[:show_redactions] && !current_user&.moderator?
+    render "browse/not_found", :status => :not_found
   end
 end
index de60de317fde2ed5c89e5e6d675b51e545d69ebe..1b3ebd747147d18e1502b51a6dd5eac08550499a 100644 (file)
@@ -1,20 +1,7 @@
-class OldWaysController < ApplicationController
-  layout :map_layout
-
-  before_action :authorize_web
-  before_action :set_locale
-  before_action -> { check_database_readable(:need_api => true) }
-  before_action :require_oauth
-
-  authorize_resource
-
-  before_action :require_moderator_for_unredacted_history
-  around_action :web_timeout
-
+class OldWaysController < OldElementsController
   def index
     @type = "way"
     @feature = Way.preload(:way_tags, :old_ways => [:old_tags, { :changeset => [:changeset_tags, :user], :old_nodes => { :node => [:node_tags, :ways] } }]).find(params[:id])
-    render "browse/history"
   rescue ActiveRecord::RecordNotFound
     render "browse/not_found", :status => :not_found
   end
@@ -23,12 +10,6 @@ class OldWaysController < ApplicationController
     @type = "way"
     @feature = OldWay.preload(:old_tags, :changeset => [:changeset_tags, :user], :old_nodes => { :node => [:node_tags, :ways] }).find([params[:id], params[:version]])
   rescue ActiveRecord::RecordNotFound
-    render :action => "not_found", :status => :not_found
-  end
-
-  private
-
-  def require_moderator_for_unredacted_history
-    deny_access(nil) if params[:show_redactions] && !current_user&.moderator?
+    render "browse/not_found", :status => :not_found
   end
 end
index 8aeefd6cccec983d13ab103d2f5e76de5bf3bc8b..9199c9e4a633a5d3945a94d5cf2c923efb45772d 100644 (file)
@@ -1,19 +1,7 @@
-class RelationsController < ApplicationController
-  layout :map_layout
-
-  before_action :authorize_web
-  before_action :set_locale
-  before_action -> { check_database_readable(:need_api => true) }
-  before_action :require_oauth
-
-  authorize_resource
-
-  around_action :web_timeout
-
+class RelationsController < ElementsController
   def show
     @type = "relation"
     @feature = Relation.preload(:relation_tags, :containing_relation_members, :changeset => [:changeset_tags, :user], :relation_members => :member).find(params[:id])
-    render "browse/feature"
   rescue ActiveRecord::RecordNotFound
     render "browse/not_found", :status => :not_found
   end
index d4abe2db7fca9e289d4e5ef163241fa26d120a50..d5c5d8736004f50672f3878787df11db86efeec5 100644 (file)
@@ -1,19 +1,7 @@
-class WaysController < ApplicationController
-  layout :map_layout
-
-  before_action :authorize_web
-  before_action :set_locale
-  before_action -> { check_database_readable(:need_api => true) }
-  before_action :require_oauth
-
-  authorize_resource
-
-  around_action :web_timeout
-
+class WaysController < ElementsController
   def show
     @type = "way"
     @feature = Way.preload(:way_tags, :containing_relation_members, :changeset => [:changeset_tags, :user], :nodes => [:node_tags, { :ways => :way_tags }]).find(params[:id])
-    render "browse/feature"
   rescue ActiveRecord::RecordNotFound
     render "browse/not_found", :status => :not_found
   end
index ae953c5833c59c59e2b135d342f0d2c7aa2f21e5..4605658f65c0a3f1f0202cd70b7e3934adad9f96 100644 (file)
@@ -41,4 +41,20 @@ module ChangesetsHelper
       t "changesets.index.title"
     end
   end
+
+  def changeset_data(changeset)
+    changeset_data = { :id => changeset.id }
+
+    if changeset.bbox_valid?
+      bbox = changeset.bbox.to_unscaled
+      changeset_data[:bbox] = {
+        :minlon => bbox.min_lon,
+        :minlat => bbox.min_lat,
+        :maxlon => bbox.max_lon,
+        :maxlat => bbox.max_lat
+      }
+    end
+
+    changeset_data
+  end
 end
index 8a3a8a3eb460f2b8c550d7daeba3c99e724e48f2..f18a6250c9e556f65892b30eca7691fd2e6f1ba4 100644 (file)
@@ -27,19 +27,15 @@ module UserBlocksHelper
 
   def block_short_status(block)
     if block.active?
-      if block.needs_view?
-        if block.ends_at > Time.now.utc
-          t("user_blocks.helper.short.active_unread")
-        else
-          t("user_blocks.helper.short.expired_unread")
-        end
-      else
+      if block.ends_at > Time.now.utc
         t("user_blocks.helper.short.active")
+      else
+        t("user_blocks.helper.short.active_until_read")
       end
     else
       if block.revoker_id.nil?
-        if block.updated_at > block.ends_at
-          t("user_blocks.helper.short.read_html", :time => block_short_time_in_past(block.updated_at))
+        if block.deactivates_at > block.ends_at
+          t("user_blocks.helper.short.read_html", :time => block_short_time_in_past(block.deactivates_at))
         else
           t("user_blocks.helper.short.ended")
         end
index dee3dafbed35562ab865f11c64fcad4d61e8a067..1dd13fb2d220787af6562f11281abb6bd0da07cc 100644 (file)
@@ -78,7 +78,7 @@ class UserMailer < ApplicationMailer
       @text = message.body
       @title = message.title
       @readurl = message_url(message)
-      @replyurl = message_reply_url(message)
+      @replyurl = new_message_reply_url(message)
       @author = @from_user
 
       attach_user_avatar(message.sender)
index a3e6f943bb9ef714979811c8c1c2e56015990a07..e31c5e90d2a7508e770a0870bde1a92e82712f5c 100644 (file)
   <fieldset class="mb-3">
     <label for="user_auth_provider" class="form-label"><%= t(".external auth") %></label>
     <div class="row">
-      <%= f.select(:auth_provider, { t("auth.providers.none") => "" }.merge(Auth.providers), :hide_label => true, :wrapper => { :class => "col-auto mb-0" }) %>
+      <%= f.select :auth_provider,
+                   Auth.providers.map { |provider| [I18n.t("auth.providers.#{provider}"), provider] },
+                   :include_blank => t("auth.providers.none"),
+                   :hide_label => true,
+                   :wrapper => { :class => "col-auto mb-0" } %>
       <%= f.text_field(:auth_uid, :hide_label => true, :wrapper => { :class => "col mb-0" }) %>
     </div>
     <small class="form-text text-body-secondary">(<a href="<%= t ".openid.link" %>" target="_new"><%= t ".openid.link text" %></a>)</small>
index 3feda6139a4473b637ae4d678fd90da8f6879be6..3edc6edd2476d9a8fd195867f7d01b832c7f29eb 100644 (file)
@@ -1,4 +1,4 @@
-<% prefered_auth_button_available = @preferred_auth_provider != "openid" && Auth.providers.value?(@preferred_auth_provider) %>
+<% prefered_auth_button_available = @preferred_auth_provider != "openid" && Auth.providers.include?(@preferred_auth_provider) %>
 
 <div>
   <%= tag.div :id => "login_auth_buttons",
@@ -11,7 +11,7 @@
     <% end %>
 
     <div class="col justify-content-center d-flex align-items-center flex-wrap gap-2">
-      <% Auth.providers.each_value do |provider| %>
+      <% Auth.providers.each do |provider| %>
         <% if provider == "openid" %>
           <%= button_tag image_tag("auth_providers/openid.svg",
                                    :alt => t(".openid.alt"),
index 36ee4c883769ee3b28da09693c025bb499ffb7a5..47b299e0310f6ed3baacd6138edfc95e29f8e314 100644 (file)
@@ -2,6 +2,4 @@
 
 <%= render "sidebar_header", :title => t(".title") %>
 
-<div>
-  <p><%= t ".sorry", :type => t(".type.#{@type}"), :id => params[:id] %>
-</div>
+<%= render "not_found_message" %>
index 2a3f6585943012583e7cb94eb413d4610c8f97f2..e29cf01b012c23a81648ad69921d36ed22bcaa49 100644 (file)
@@ -1,16 +1,4 @@
-<% changeset_data = { :id => changeset.id }
-
-   if changeset.bbox_valid?
-     bbox = changeset.bbox.to_unscaled
-     changeset_data[:bbox] = {
-       :minlon => bbox.min_lon,
-       :minlat => bbox.min_lat,
-       :maxlon => bbox.max_lon,
-       :maxlat => bbox.max_lat
-     }
-   end %>
-
-<%= tag.li :id => "changeset_#{changeset.id}", :data => { :changeset => changeset_data }, :class => "list-group-item list-group-item-action" do %>
+<%= tag.li :id => "changeset_#{changeset.id}", :data => { :changeset => changeset_data(changeset) }, :class => "list-group-item list-group-item-action" do %>
   <p class="fs-6 text-truncate text-wrap">
     <a class="changeset_id link-body-emphasis stretched-link" href="<%= changeset_path(changeset) %>">
       <span><%= changeset.tags["comment"].to_s.presence || t("browse.no_comment") %></span>
diff --git a/app/views/changesets/_not_found_message.html.erb b/app/views/changesets/_not_found_message.html.erb
new file mode 100644 (file)
index 0000000..9297f3b
--- /dev/null
@@ -0,0 +1,3 @@
+<div>
+  <p><%= t ".sorry", :id => params[:id] %></p>
+</div>
index a47049e999620a70effb50d2d5edb0a30db41229..167bcb5cb807d5fc2d147a049853b2284125d25b 100644 (file)
@@ -6,7 +6,9 @@
   <p class="fs-6 overflow-x-auto">
     <%= linkify(@changeset.tags["comment"].to_s.presence || t("browse.no_comment")) %>
   </p>
-  <p class="details"><%= changeset_details(@changeset) %></p>
+  <%= tag.p :class => "details", :data => { :changeset => changeset_data(@changeset) } do %>
+    <%= changeset_details(@changeset) %>
+  <% end %>
 
   <%= render :partial => "browse/tag_details", :object => @changeset.tags.except("comment") %>
 
index 99d6d0435512d0f8e33ef8ccc3112dec762ad20f..d3147c9699c3c24c95b1a12aa2c7d74acf24be0c 100644 (file)
@@ -18,7 +18,7 @@
 <div class="richtext text-break"><%= @message.body.to_html %></div>
 
 <div>
-  <%= link_to t(".reply_button"), message_reply_path(@message), :class => "btn btn-primary" %>
+  <%= link_to t(".reply_button"), new_message_reply_path(@message), :class => "btn btn-primary" %>
   <% if current_user == @message.recipient %>
     <%= link_to t(".unread_button"), message_mark_path(@message, :mark => "unread"), :method => "post", :class => "btn btn-primary" %>
     <%= link_to t(".destroy_button"), message_path(@message), :method => "delete", :class => "btn btn-danger" %>
diff --git a/app/views/nodes/_not_found_message.html.erb b/app/views/nodes/_not_found_message.html.erb
new file mode 100644 (file)
index 0000000..9297f3b
--- /dev/null
@@ -0,0 +1,3 @@
+<div>
+  <p><%= t ".sorry", :id => params[:id] %></p>
+</div>
diff --git a/app/views/notes/_not_found_message.html.erb b/app/views/notes/_not_found_message.html.erb
new file mode 100644 (file)
index 0000000..9297f3b
--- /dev/null
@@ -0,0 +1,3 @@
+<div>
+  <p><%= t ".sorry", :id => params[:id] %></p>
+</div>
similarity index 87%
rename from app/views/browse/_version_actions.erb
rename to app/views/old_elements/_actions.html.erb
index 94e18e45777bb27e950f573b7d86039634fe0b4a..36a16abb4543ffb74c3a00276c5e34e9d877b932 100644 (file)
@@ -6,9 +6,9 @@
   <% elsif current_user&.moderator? %>
     &middot;
     <% if !params[:show_redactions] %>
-      <%= link_to t("browse.view_redacted_data"), :params => { :show_redactions => true } %>
+      <%= link_to t(".view_redacted_data"), :params => { :show_redactions => true } %>
     <% else %>
-      <%= link_to t("browse.view_redaction_message") %>
+      <%= link_to t(".view_redaction_message") %>
     <% end %>
   <% end %>
 </div>
similarity index 72%
rename from app/views/browse/history.html.erb
rename to app/views/old_elements/index.html.erb
index 1595df0216d129772d953d07c5a5923d85f32fa8..d4ecbfa60480c618041bb7902bd601abd91ec644 100644 (file)
@@ -1,6 +1,6 @@
-<% set_title(t("browse.#{@type}.history_title_html", :name => printable_element_name(@feature))) %>
+<% set_title(t(".#{@type}.title_html", :name => printable_element_name(@feature))) %>
 
-<%= render "sidebar_header", :title => t("browse.#{@type}.history_title_html", :name => printable_element_name(@feature)) %>
+<%= render "sidebar_header", :title => t(".#{@type}.title_html", :name => printable_element_name(@feature)) %>
 
 <%= render :partial => "browse/#{@type}", :collection => @feature.send(:"old_#{@type}s").reverse %>
 
diff --git a/app/views/old_nodes/_not_found_message.html.erb b/app/views/old_nodes/_not_found_message.html.erb
new file mode 100644 (file)
index 0000000..402905a
--- /dev/null
@@ -0,0 +1,7 @@
+<div>
+  <% if params[:version] %>
+    <p><%= t ".sorry", :id => params[:id], :version => params[:version] %></p>
+  <% else %>
+    <p><%= t "nodes.not_found_message.sorry", :id => params[:id] %></p>
+  <% end %>
+</div>
diff --git a/app/views/old_nodes/not_found.html.erb b/app/views/old_nodes/not_found.html.erb
deleted file mode 100644 (file)
index 1ee5d9d..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<% set_title(t("browse.not_found.title")) %>
-
-<%= render "sidebar_header", :title => t("browse.not_found.title") %>
-
-<div>
-  <p><%= t ".sorry", :id => params[:id], :version => params[:version] %></p>
-</div>
index 093a3e7c15c962c45ca5694adbeebf45c71737ba..ad6b75ab10468a67ef145c30d15021e66f0f92a6 100644 (file)
@@ -4,4 +4,4 @@
 
 <%= render :partial => "browse/node", :object => @feature %>
 
-<%= render :partial => "browse/version_actions" %>
+<%= render :partial => "actions" %>
diff --git a/app/views/old_relations/_not_found_message.html.erb b/app/views/old_relations/_not_found_message.html.erb
new file mode 100644 (file)
index 0000000..a4598eb
--- /dev/null
@@ -0,0 +1,7 @@
+<div>
+  <% if params[:version] %>
+    <p><%= t ".sorry", :id => params[:id], :version => params[:version] %></p>
+  <% else %>
+    <p><%= t "relations.not_found_message.sorry", :id => params[:id] %></p>
+  <% end %>
+</div>
diff --git a/app/views/old_relations/not_found.html.erb b/app/views/old_relations/not_found.html.erb
deleted file mode 100644 (file)
index 1ee5d9d..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<% set_title(t("browse.not_found.title")) %>
-
-<%= render "sidebar_header", :title => t("browse.not_found.title") %>
-
-<div>
-  <p><%= t ".sorry", :id => params[:id], :version => params[:version] %></p>
-</div>
index 94e3674d8759432efae525c54c215141791c2774..bfed1fb877ed5a06d4668657900d0c33ebe362f6 100644 (file)
@@ -4,4 +4,4 @@
 
 <%= render :partial => "browse/relation", :object => @feature %>
 
-<%= render :partial => "browse/version_actions" %>
+<%= render :partial => "actions" %>
diff --git a/app/views/old_ways/_not_found_message.html.erb b/app/views/old_ways/_not_found_message.html.erb
new file mode 100644 (file)
index 0000000..09c97ac
--- /dev/null
@@ -0,0 +1,7 @@
+<div>
+  <% if params[:version] %>
+    <p><%= t ".sorry", :id => params[:id], :version => params[:version] %></p>
+  <% else %>
+    <p><%= t "ways.not_found_message.sorry", :id => params[:id] %></p>
+  <% end %>
+</div>
diff --git a/app/views/old_ways/not_found.html.erb b/app/views/old_ways/not_found.html.erb
deleted file mode 100644 (file)
index 1ee5d9d..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<% set_title(t("browse.not_found.title")) %>
-
-<%= render "sidebar_header", :title => t("browse.not_found.title") %>
-
-<div>
-  <p><%= t ".sorry", :id => params[:id], :version => params[:version] %></p>
-</div>
index 1e4d14c805ceb079d53d3eeba02d858e445d2ac8..213ad13b0b5d43216d3a89706ea4d4cea8232fb1 100644 (file)
@@ -4,4 +4,4 @@
 
 <%= render :partial => "browse/way", :object => @feature %>
 
-<%= render :partial => "browse/version_actions" %>
+<%= render :partial => "actions" %>
diff --git a/app/views/relations/_not_found_message.html.erb b/app/views/relations/_not_found_message.html.erb
new file mode 100644 (file)
index 0000000..9297f3b
--- /dev/null
@@ -0,0 +1,3 @@
+<div>
+  <p><%= t ".sorry", :id => params[:id] %></p>
+</div>
diff --git a/app/views/ways/_not_found_message.html.erb b/app/views/ways/_not_found_message.html.erb
new file mode 100644 (file)
index 0000000..9297f3b
--- /dev/null
@@ -0,0 +1,3 @@
+<div>
+  <p><%= t ".sorry", :id => params[:id] %></p>
+</div>
index 4f2174206548e2f5267daf6ad4c39a896c9e710d..fcaf6ddfe8ddd0f27a3b5d2256f7adb3240624cc 100644 (file)
@@ -245,25 +245,6 @@ en:
       entry:
         comment: Comment
         full: Full note
-  account:
-    deletions:
-      show:
-        title: Delete My Account
-        warning: Warning! The account deletion process is final, and cannot be reversed.
-        delete_account: Delete Account
-        delete_introduction: "You can delete your OpenStreetMap account using the button below. Please note the following details:"
-        delete_profile: Your profile information, including your avatar, description and home location will be removed.
-        delete_display_name: Your display name will be removed, and can be reused by other accounts.
-        retain_caveats: "However, some information about you will be retained on OpenStreetMap, even after your account is deleted:"
-        retain_edits: Your edits to the map database, if any, will be retained.
-        retain_traces: Your uploaded traces, if any, will be retained.
-        retain_diary_entries: Your diary entries and diary comments, if any, will be retained but hidden from view.
-        retain_notes: Your map notes and note comments, if any, will be retained but hidden from view.
-        retain_changeset_discussions: Your changeset discussions, if any, will be retained.
-        retain_email: Your email address will be retained.
-        recent_editing_html: "As you have edited recently your account cannot currently be deleted. Deletion will be possible in %{time}."
-        confirm_delete: Are you sure?
-        cancel: Cancel
   accounts:
     edit:
       title: "Edit account"
@@ -305,6 +286,24 @@ en:
       success: "User information updated successfully."
     destroy:
       success: "Account Deleted."
+    deletions:
+      show:
+        title: Delete My Account
+        warning: Warning! The account deletion process is final, and cannot be reversed.
+        delete_account: Delete Account
+        delete_introduction: "You can delete your OpenStreetMap account using the button below. Please note the following details:"
+        delete_profile: Your profile information, including your avatar, description and home location will be removed.
+        delete_display_name: Your display name will be removed, and can be reused by other accounts.
+        retain_caveats: "However, some information about you will be retained on OpenStreetMap, even after your account is deleted:"
+        retain_edits: Your edits to the map database, if any, will be retained.
+        retain_traces: Your uploaded traces, if any, will be retained.
+        retain_diary_entries: Your diary entries and diary comments, if any, will be retained but hidden from view.
+        retain_notes: Your map notes and note comments, if any, will be retained but hidden from view.
+        retain_changeset_discussions: Your changeset discussions, if any, will be retained.
+        retain_email: Your email address will be retained.
+        recent_editing_html: "As you have edited recently your account cannot currently be deleted. Deletion will be possible in %{time}."
+        confirm_delete: Are you sure?
+        cancel: Cancel
   browse:
     deleted_ago_by_html: "Deleted %{time_ago} by %{user}"
     edited_ago_by_html: "Edited %{time_ago} by %{user}"
@@ -324,17 +323,13 @@ en:
     view_history: "View History"
     view_unredacted_history: "View Unredacted History"
     view_details: "View Details"
-    view_redacted_data: "View Redacted Data"
-    view_redaction_message: "View Redaction Message"
     location: "Location:"
     common_details:
       coordinates_html: "%{latitude}, %{longitude}"
     node:
       title_html: "Node: %{name}"
-      history_title_html: "Node History: %{name}"
     way:
       title_html: "Way: %{name}"
-      history_title_html: "Way History: %{name}"
       nodes: "Nodes"
       nodes_count:
         one: "%{count} node"
@@ -344,7 +339,6 @@ en:
         other: "part of ways %{related_ways}"
     relation:
       title_html: "Relation: %{name}"
-      history_title_html: "Relation History: %{name}"
       members: "Members"
       members_count:
         one: "%{count} member"
@@ -360,13 +354,6 @@ en:
       entry_role_html: "%{relation_name} (as %{relation_role})"
     not_found:
       title: Not Found
-      sorry: "Sorry, %{type} #%{id} could not be found."
-      type:
-        node: node
-        way: way
-        relation: relation
-        changeset: changeset
-        note: note
     timeout:
       title: Timeout Error
       sorry: "Sorry, the data for the %{type} with the id %{id} took too long to retrieve."
@@ -403,27 +390,44 @@ en:
       introduction: "Click on the map to find nearby features."
       nearby: "Nearby features"
       enclosing: "Enclosing features"
+  old_elements:
+    index:
+      node:
+        title_html: "Node History: %{name}"
+      way:
+        title_html: "Way History: %{name}"
+      relation:
+        title_html: "Relation History: %{name}"
+    actions:
+      view_redacted_data: "View Redacted Data"
+      view_redaction_message: "View Redaction Message"
   nodes:
+    not_found_message:
+      sorry: "Sorry, node #%{id} could not be found."
     timeout:
       sorry: "Sorry, the data for the node with the id %{id} took too long to retrieve."
   old_nodes:
-    not_found:
+    not_found_message:
       sorry: "Sorry, node #%{id} version %{version} could not be found."
     timeout:
       sorry: "Sorry, the history of the node with the id %{id} took too long to retrieve."
   ways:
+    not_found_message:
+      sorry: "Sorry, way #%{id} could not be found."
     timeout:
       sorry: "Sorry, the data for the way with the id %{id} took too long to retrieve."
   old_ways:
-    not_found:
+    not_found_message:
       sorry: "Sorry, way #%{id} version %{version} could not be found."
     timeout:
       sorry: "Sorry, the history of the way with the id %{id} took too long to retrieve."
   relations:
+    not_found_message:
+      sorry: "Sorry, relation #%{id} could not be found."
     timeout:
       sorry: "Sorry, the data for the relation with the id %{id} took too long to retrieve."
   old_relations:
-    not_found:
+    not_found_message:
       sorry: "Sorry, relation #%{id} version %{version} could not be found."
     timeout:
       sorry: "Sorry, the history of the relation with the id %{id} took too long to retrieve."
@@ -499,6 +503,8 @@ en:
       ways_paginated: "Ways (%{x}-%{y} of %{count})"
       relations: "Relations (%{count})"
       relations_paginated: "Relations (%{x}-%{y} of %{count})"
+    not_found_message:
+      sorry: "Sorry, changeset #%{id} could not be found."
     timeout:
       sorry: "Sorry, the list of changesets you requested took too long to retrieve."
   dashboards:
@@ -1752,8 +1758,6 @@ en:
       title: "No such message"
       heading: "No such message"
       body: "Sorry there is no message with that id."
-    reply:
-      wrong_user: "You are logged in as '%{user}' but the message you have asked to reply to was not sent to that user. Please log in as the correct user in order to reply."
     show:
       title: "Read message"
       reply_button: "Reply"
@@ -1813,6 +1817,9 @@ en:
         people_mapping_nearby: "people mapping nearby"
       message:
         destroy_button: "Delete"
+    replies:
+      new:
+        wrong_user: "You are logged in as '%{user}' but the message you have asked to reply to was not sent to that user. Please log in as the correct user in order to reply."
   passwords:
     new:
       title: "Lost password"
@@ -2972,8 +2979,7 @@ en:
         ended: "ended"
         revoked_html: "revoked by %{name}"
         active: "active"
-        active_unread: "active unread"
-        expired_unread: "expired unread"
+        active_until_read: "active until read"
         read_html: "read at %{time}"
         time_in_future_title: "%{time_absolute}; in %{time_relative}"
         time_in_past_title: "%{time_absolute}; %{time_relative}"
@@ -3091,6 +3097,8 @@ en:
       showing_page: "Page %{page}"
       next: "Next"
       previous: "Previous"
+    not_found_message:
+      sorry: "Sorry, note #%{id} could not be found."
   javascripts:
     close: Close
     share:
index e623a0738eb24f0978cf014157a6d3c879c13d49..d89068c14002c7398b0a80128c1e96d1628a4006 100644 (file)
@@ -277,11 +277,10 @@ OpenStreetMap::Application.routes.draw do
   get "/user/:display_name/account", :to => redirect(:path => "/account/edit")
   post "/user/:display_name/set_status" => "users#set_status", :as => :set_status_user
 
-  resource :account, :only => [:edit, :update, :destroy]
-
-  namespace :account do
-    resource :deletion, :only => [:show]
+  resource :account, :only => [:edit, :update, :destroy] do
+    resource :deletion, :module => :accounts, :only => :show
   end
+
   resource :dashboard, :only => [:show]
   resource :preferences, :only => [:show, :edit, :update]
   resource :profile, :only => [:edit, :update]
@@ -313,7 +312,7 @@ OpenStreetMap::Application.routes.draw do
     post :mark
     patch :unmute
 
-    match :reply, :via => [:get, :post]
+    resource :reply, :module => :messages, :path_names => { :new => "new" }, :only => :new
   end
   namespace :messages, :path => "/messages" do
     resource :inbox, :only => :show
@@ -324,6 +323,7 @@ OpenStreetMap::Application.routes.draw do
   get "/user/:display_name/outbox", :to => redirect(:path => "/messages/outbox")
   get "/message/new/:display_name", :to => redirect(:path => "/messages/new/%{display_name}")
   get "/message/read/:message_id", :to => redirect(:path => "/messages/%{message_id}")
+  get "/messages/:message_id/reply", :to => redirect(:path => "/messages/%{message_id}/reply/new")
 
   # muting users
   scope "/user/:display_name" do
index 729772477757ac810113e6abf77a92fead58e904..2c6d0c1d7036ad5f4f2d4f1e6a53593f3048b65d 100644 (file)
@@ -1,15 +1,13 @@
 module Auth
-  @providers = {}
+  @providers = ["openid"]
+  @providers << "google" if Settings.key?(:google_auth_id)
+  @providers << "facebook" if Settings.key?(:facebook_auth_id)
+  @providers << "microsoft" if Settings.key?(:microsoft_auth_id)
+  @providers << "github" if Settings.key?(:github_auth_id)
+  @providers << "wikipedia" if Settings.key?(:wikipedia_auth_id)
+  @providers.freeze
 
   def self.providers
-    @providers[I18n.locale] ||= {
-      I18n.t("auth.providers.openid") => "openid"
-    }.tap do |providers|
-      providers[I18n.t("auth.providers.google")] = "google" if Settings.key?(:google_auth_id)
-      providers[I18n.t("auth.providers.facebook")] = "facebook" if Settings.key?(:facebook_auth_id)
-      providers[I18n.t("auth.providers.microsoft")] = "microsoft" if Settings.key?(:microsoft_auth_id)
-      providers[I18n.t("auth.providers.github")] = "github" if Settings.key?(:github_auth_id)
-      providers[I18n.t("auth.providers.wikipedia")] = "wikipedia" if Settings.key?(:wikipedia_auth_id)
-    end.freeze
+    @providers
   end
 end
index 65a71a9b57b05d8f4eda9c53a4f535d143d270b5..3ea9bc09400d5334d3a80044d68089736591b427 100644 (file)
@@ -104,6 +104,7 @@ class DiaryCommentsControllerTest < ActionDispatch::IntegrationTest
     end
     assert_response :success
     assert_template :new
+    assert_match(/img-src \* data:;/, @response.headers["Content-Security-Policy-Report-Only"])
 
     # Now try again with the right id
     assert_difference "ActionMailer::Base.deliveries.size", entry.subscribers.count do
diff --git a/test/controllers/messages/replies_controller_test.rb b/test/controllers/messages/replies_controller_test.rb
new file mode 100644 (file)
index 0000000..a839a44
--- /dev/null
@@ -0,0 +1,69 @@
+require "test_helper"
+
+module Messages
+  class RepliesControllerTest < ActionDispatch::IntegrationTest
+    ##
+    # test all routes which lead to this controller
+    def test_routes
+      assert_routing(
+        { :path => "/messages/1/reply/new", :method => :get },
+        { :controller => "messages/replies", :action => "new", :message_id => "1" }
+      )
+    end
+
+    def test_new
+      user = create(:user)
+      recipient_user = create(:user)
+      other_user = create(:user)
+      message = create(:message, :unread, :sender => user, :recipient => recipient_user)
+
+      # Check that the message reply page requires us to login
+      get new_message_reply_path(message)
+      assert_redirected_to login_path(:referer => new_message_reply_path(message))
+
+      # Login as the wrong user
+      session_for(other_user)
+
+      # Check that we can't reply to somebody else's message
+      get new_message_reply_path(message)
+      assert_redirected_to login_path(:referer => new_message_reply_path(message))
+      assert_equal "You are logged in as '#{other_user.display_name}' but the message you have asked to reply to was not sent to that user. Please log in as the correct user in order to reply.", flash[:notice]
+
+      # Login as the right user
+      session_for(recipient_user)
+
+      # Check that the message reply page loads
+      get new_message_reply_path(message)
+      assert_response :success
+      assert_template "new"
+      assert_select "title", "Re: #{message.title} | OpenStreetMap"
+      assert_select "form[action='/messages']", :count => 1 do
+        assert_select "input[type='hidden'][name='display_name'][value='#{user.display_name}']"
+        assert_select "input#message_title[value='Re: #{message.title}']", :count => 1
+        assert_select "textarea#message_body", :count => 1
+        assert_select "input[type='submit'][value='Send']", :count => 1
+      end
+      assert Message.find(message.id).message_read
+
+      # Login as the sending user
+      session_for(user)
+
+      # Check that the message reply page loads
+      get new_message_reply_path(message)
+      assert_response :success
+      assert_template "new"
+      assert_select "title", "Re: #{message.title} | OpenStreetMap"
+      assert_select "form[action='/messages']", :count => 1 do
+        assert_select "input[type='hidden'][name='display_name'][value='#{recipient_user.display_name}']"
+        assert_select "input#message_title[value='Re: #{message.title}']", :count => 1
+        assert_select "textarea#message_body", :count => 1
+        assert_select "input[type='submit'][value='Send']", :count => 1
+      end
+
+      # Asking to reply to a message with a bogus ID should fail
+      get new_message_reply_path(99999)
+      assert_response :not_found
+      assert_template "no_such_message"
+    end
+  end
+end
index f72e695936813142a723b4aaef28cf6bb8c4f0ec..b2bb71b1c71e8b1484983d9956f89487b55d5d21 100644 (file)
@@ -20,14 +20,6 @@ class MessagesControllerTest < ActionDispatch::IntegrationTest
       { :path => "/messages/1/mark", :method => :post },
       { :controller => "messages", :action => "mark", :message_id => "1" }
     )
-    assert_routing(
-      { :path => "/messages/1/reply", :method => :get },
-      { :controller => "messages", :action => "reply", :message_id => "1" }
-    )
-    assert_routing(
-      { :path => "/messages/1/reply", :method => :post },
-      { :controller => "messages", :action => "reply", :message_id => "1" }
-    )
     assert_routing(
       { :path => "/messages/1", :method => :delete },
       { :controller => "messages", :action => "destroy", :id => "1" }
@@ -171,7 +163,7 @@ class MessagesControllerTest < ActionDispatch::IntegrationTest
         end
       end
     end
-    assert_redirected_to messages_inbox_path
+    assert_redirected_to messages_outbox_path
     assert_equal "Message sent", flash[:notice]
     e = ActionMailer::Base.deliveries.first
     assert_equal [recipient_user.email], e.to
@@ -219,63 +211,6 @@ class MessagesControllerTest < ActionDispatch::IntegrationTest
     end
   end
 
-  ##
-  # test the reply action
-  def test_reply
-    user = create(:user)
-    recipient_user = create(:user)
-    other_user = create(:user)
-    message = create(:message, :unread, :sender => user, :recipient => recipient_user)
-
-    # Check that the message reply page requires us to login
-    get message_reply_path(message)
-    assert_redirected_to login_path(:referer => message_reply_path(message))
-
-    # Login as the wrong user
-    session_for(other_user)
-
-    # Check that we can't reply to somebody else's message
-    get message_reply_path(message)
-    assert_redirected_to login_path(:referer => message_reply_path(message))
-    assert_equal "You are logged in as '#{other_user.display_name}' but the message you have asked to reply to was not sent to that user. Please log in as the correct user in order to reply.", flash[:notice]
-
-    # Login as the right user
-    session_for(recipient_user)
-
-    # Check that the message reply page loads
-    get message_reply_path(message)
-    assert_response :success
-    assert_template "new"
-    assert_select "title", "Re: #{message.title} | OpenStreetMap"
-    assert_select "form[action='/messages']", :count => 1 do
-      assert_select "input[type='hidden'][name='display_name'][value='#{user.display_name}']"
-      assert_select "input#message_title[value='Re: #{message.title}']", :count => 1
-      assert_select "textarea#message_body", :count => 1
-      assert_select "input[type='submit'][value='Send']", :count => 1
-    end
-    assert Message.find(message.id).message_read
-
-    # Login as the sending user
-    session_for(user)
-
-    # Check that the message reply page loads
-    get message_reply_path(message)
-    assert_response :success
-    assert_template "new"
-    assert_select "title", "Re: #{message.title} | OpenStreetMap"
-    assert_select "form[action='/messages']", :count => 1 do
-      assert_select "input[type='hidden'][name='display_name'][value='#{recipient_user.display_name}']"
-      assert_select "input#message_title[value='Re: #{message.title}']", :count => 1
-      assert_select "textarea#message_body", :count => 1
-      assert_select "input[type='submit'][value='Send']", :count => 1
-    end
-
-    # Asking to reply to a message with a bogus ID should fail
-    get message_reply_path(99999)
-    assert_response :not_found
-    assert_template "no_such_message"
-  end
-
   ##
   # test the show action
   def test_show
index a294327231d78ca0b54b5e5f338ae305f27221d6..6db340c214123c026501ad711263468d0c776d35 100644 (file)
@@ -12,7 +12,7 @@ class NodesControllerTest < ActionDispatch::IntegrationTest
 
   def test_show
     node = create(:node)
-    sidebar_browse_check :node_path, node.id, "browse/feature"
+    sidebar_browse_check :node_path, node.id, "elements/show"
     assert_select "h4", /^Version/ do
       assert_select "a[href='#{old_node_path node, 1}']", :text => "1", :count => 1
     end
@@ -23,7 +23,7 @@ class NodesControllerTest < ActionDispatch::IntegrationTest
 
   def test_show_multiple_versions
     node = create(:node, :with_history, :version => 2)
-    sidebar_browse_check :node_path, node.id, "browse/feature"
+    sidebar_browse_check :node_path, node.id, "elements/show"
     assert_select ".secondary-actions a[href='#{node_history_path node}']", :count => 1
     assert_select ".secondary-actions a[href='#{old_node_path node, 1}']", :count => 1
     assert_select ".secondary-actions a[href='#{old_node_path node, 2}']", :count => 1
@@ -33,13 +33,13 @@ class NodesControllerTest < ActionDispatch::IntegrationTest
     member = create(:node)
     relation = create(:relation)
     create(:relation_member, :relation => relation, :member => member)
-    sidebar_browse_check :node_path, member.id, "browse/feature"
+    sidebar_browse_check :node_path, member.id, "elements/show"
     assert_select "a[href='#{relation_path relation}']", :count => 1
   end
 
   def test_show_deleted
     node = create(:node, :visible => false)
-    sidebar_browse_check :node_path, node.id, "browse/feature"
+    sidebar_browse_check :node_path, node.id, "elements/show"
     assert_select "h4", /^Version/ do
       assert_select "a[href='#{old_node_path node, 1}']", :text => "1", :count => 1
     end
@@ -53,7 +53,7 @@ class NodesControllerTest < ActionDispatch::IntegrationTest
 
     get node_path(node)
     assert_response :success
-    assert_template "feature"
+    assert_template "elements/show"
 
     # check that we don't show lat/lon for a redacted node.
     assert_select ".browse-section", 1
index abaf30d62e68563e5f694e0a015b7e57668f77b4..8e3a14ab6c8717a5860dbb7a1d8ed2284ce9bad2 100644 (file)
@@ -14,7 +14,7 @@ class OldNodesControllerTest < ActionDispatch::IntegrationTest
 
   def test_history
     node = create(:node, :with_history)
-    sidebar_browse_check :node_history_path, node.id, "browse/history"
+    sidebar_browse_check :node_history_path, node.id, "old_elements/index"
     assert_select "h4", /^Version/ do
       assert_select "a[href='#{old_node_path node, 1}']", :text => "1", :count => 1
     end
@@ -27,7 +27,7 @@ class OldNodesControllerTest < ActionDispatch::IntegrationTest
 
     get node_history_path(:id => node)
     assert_response :success
-    assert_template "browse/history"
+    assert_template "old_elements/index"
 
     # there are 2 revisions of the redacted node, but only one
     # should be showing details here.
@@ -46,7 +46,7 @@ class OldNodesControllerTest < ActionDispatch::IntegrationTest
 
     get node_history_path(:id => node, :params => { :show_redactions => true })
     assert_response :success
-    assert_template "browse/history"
+    assert_template "old_elements/index"
 
     assert_select ".browse-section", 2
     assert_select ".browse-section.browse-redacted", 0
@@ -213,7 +213,7 @@ class OldNodesControllerTest < ActionDispatch::IntegrationTest
   def test_not_found
     get old_node_path(0, 0)
     assert_response :not_found
-    assert_template "old_nodes/not_found"
+    assert_template "browse/not_found"
     assert_template :layout => "map"
     assert_select "#sidebar_content", /node #0 version 0 could not be found/
   end
index f5de706cf59e92220e4ec5c2348e6dd9e06c7a9c..3ede1842b5d35137602c92dde30a3ddf1e83f9b2 100644 (file)
@@ -14,7 +14,7 @@ class OldRelationsControllerTest < ActionDispatch::IntegrationTest
 
   def test_history
     relation = create(:relation, :with_history)
-    sidebar_browse_check :relation_history_path, relation.id, "browse/history"
+    sidebar_browse_check :relation_history_path, relation.id, "old_elements/index"
     assert_select "h4", /^Version/ do
       assert_select "a[href='#{old_relation_path relation, 1}']", :text => "1", :count => 1
     end
@@ -29,7 +29,7 @@ class OldRelationsControllerTest < ActionDispatch::IntegrationTest
 
     get relation_history_path(:id => relation)
     assert_response :success
-    assert_template "browse/history"
+    assert_template "old_elements/index"
 
     # there are 4 revisions of the redacted relation, but only 2
     # should be showing details here.
@@ -48,7 +48,7 @@ class OldRelationsControllerTest < ActionDispatch::IntegrationTest
 
     get relation_history_path(:id => relation, :params => { :show_redactions => true })
     assert_response :success
-    assert_template "browse/history"
+    assert_template "old_elements/index"
 
     assert_select ".browse-section", 4
     assert_select ".browse-section.browse-redacted", 0
@@ -172,7 +172,7 @@ class OldRelationsControllerTest < ActionDispatch::IntegrationTest
   def test_not_found
     get old_relation_path(0, 0)
     assert_response :not_found
-    assert_template "old_relations/not_found"
+    assert_template "browse/not_found"
     assert_template :layout => "map"
     assert_select "#sidebar_content", /relation #0 version 0 could not be found/
   end
index fcc2281b85753cec329c579cf81366a76a171fd2..c7b383202bb45081f2396b4a916e93108f9ab606 100644 (file)
@@ -14,7 +14,7 @@ class OldWaysControllerTest < ActionDispatch::IntegrationTest
 
   def test_history
     way = create(:way, :with_history)
-    sidebar_browse_check :way_history_path, way.id, "browse/history"
+    sidebar_browse_check :way_history_path, way.id, "old_elements/index"
     assert_select "h4", /^Version/ do
       assert_select "a[href='#{old_way_path way, 1}']", :text => "1", :count => 1
     end
@@ -29,7 +29,7 @@ class OldWaysControllerTest < ActionDispatch::IntegrationTest
 
     get way_history_path(:id => way)
     assert_response :success
-    assert_template "browse/history"
+    assert_template "old_elements/index"
 
     # there are 4 revisions of the redacted way, but only 2
     # should be showing details here.
@@ -48,7 +48,7 @@ class OldWaysControllerTest < ActionDispatch::IntegrationTest
 
     get way_history_path(:id => way, :params => { :show_redactions => true })
     assert_response :success
-    assert_template "browse/history"
+    assert_template "old_elements/index"
 
     assert_select ".browse-section", 4
     assert_select ".browse-section.browse-redacted", 0
@@ -177,7 +177,7 @@ class OldWaysControllerTest < ActionDispatch::IntegrationTest
   def test_not_found
     get old_way_path(0, 0)
     assert_response :not_found
-    assert_template "old_ways/not_found"
+    assert_template "browse/not_found"
     assert_template :layout => "map"
     assert_select "#sidebar_content", /way #0 version 0 could not be found/
   end
index bdcbd2fd7bf386df6d0e49887761394808fbff1f..0f07a1a4a3b042927e4877db454fed5366ee86fe 100644 (file)
@@ -12,7 +12,7 @@ class RelationsControllerTest < ActionDispatch::IntegrationTest
 
   def test_show
     relation = create(:relation)
-    sidebar_browse_check :relation_path, relation.id, "browse/feature"
+    sidebar_browse_check :relation_path, relation.id, "elements/show"
     assert_select "h4", /^Version/ do
       assert_select "a[href='#{old_relation_path relation, 1}']", :text => "1", :count => 1
     end
@@ -23,7 +23,7 @@ class RelationsControllerTest < ActionDispatch::IntegrationTest
 
   def test_show_multiple_versions
     relation = create(:relation, :with_history, :version => 2)
-    sidebar_browse_check :relation_path, relation.id, "browse/feature"
+    sidebar_browse_check :relation_path, relation.id, "elements/show"
     assert_select ".secondary-actions a[href='#{relation_history_path relation}']", :count => 1
     assert_select ".secondary-actions a[href='#{old_relation_path relation, 1}']", :count => 1
     assert_select ".secondary-actions a[href='#{old_relation_path relation, 2}']", :count => 1
@@ -33,7 +33,7 @@ class RelationsControllerTest < ActionDispatch::IntegrationTest
     member = create(:relation)
     relation = create(:relation)
     create(:relation_member, :relation => relation, :member => member)
-    sidebar_browse_check :relation_path, member.id, "browse/feature"
+    sidebar_browse_check :relation_path, member.id, "elements/show"
     assert_select "a[href='#{relation_path relation}']", :count => 1
   end
 
index 10875b068b9d586c8c81ae38b438364d3ad33447..e021513da6fdce0552c09900c6f10b7cb2d21bb8 100644 (file)
@@ -57,6 +57,8 @@ class UsersControllerTest < ActionDispatch::IntegrationTest
     get new_user_path, :params => { :cookie_test => "true" }
     assert_response :success
 
+    assert_no_match(/img-src \* data:;/, @response.headers["Content-Security-Policy-Report-Only"])
+
     assert_select "html", :count => 1 do
       assert_select "head", :count => 1 do
         assert_select "title", :text => /Sign Up/, :count => 1
@@ -297,6 +299,7 @@ class UsersControllerTest < ActionDispatch::IntegrationTest
 
     get user_path(user)
     assert_response :success
+    assert_match(/img-src \* data:;/, @response.headers["Content-Security-Policy-Report-Only"])
     assert_select "div.content-heading" do
       assert_select "a[href^='/user/#{ERB::Util.u(user.display_name)}/history']", 1
       assert_select "a[href='/user/#{ERB::Util.u(user.display_name)}/traces']", 1
index 995004cb4179236a95c8998263b90e872ae9366b..5b80a070cffcd7ef0e7d04f43b5561ccea6d9c93 100644 (file)
@@ -12,7 +12,7 @@ class WaysControllerTest < ActionDispatch::IntegrationTest
 
   def test_show
     way = create(:way)
-    sidebar_browse_check :way_path, way.id, "browse/feature"
+    sidebar_browse_check :way_path, way.id, "elements/show"
     assert_select "h4", /^Version/ do
       assert_select "a[href='#{old_way_path way, 1}']", :text => "1", :count => 1
     end
@@ -23,7 +23,7 @@ class WaysControllerTest < ActionDispatch::IntegrationTest
 
   def test_show_multiple_versions
     way = create(:way, :with_history, :version => 2)
-    sidebar_browse_check :way_path, way.id, "browse/feature"
+    sidebar_browse_check :way_path, way.id, "elements/show"
     assert_select ".secondary-actions a[href='#{way_history_path way}']", :count => 1
     assert_select ".secondary-actions a[href='#{old_way_path way, 1}']", :count => 1
     assert_select ".secondary-actions a[href='#{old_way_path way, 2}']", :count => 1
@@ -33,7 +33,7 @@ class WaysControllerTest < ActionDispatch::IntegrationTest
     member = create(:way)
     relation = create(:relation)
     create(:relation_member, :relation => relation, :member => member)
-    sidebar_browse_check :way_path, member.id, "browse/feature"
+    sidebar_browse_check :way_path, member.id, "elements/show"
     assert_select "a[href='#{relation_path relation}']", :count => 1
   end
 
index db4fd87a49a8d9672bd0785437f64f0cc5b1ca28..d308f46ead1cc04cc9dbf0ed806a431824f0ce2d 100644 (file)
@@ -14,6 +14,63 @@ class UserBlocksHelperTest < ActionView::TestCase
     assert_match %r{^Ends in <time title=".* datetime=".*">about 1 hour</time>\.$}, block_status(block)
   end
 
+  def test_block_short_status
+    freeze_time do
+      future_end_block = create(:user_block, :ends_at => Time.now.utc + 48.hours)
+      unread_future_end_block = create(:user_block, :needs_view, :ends_at => Time.now.utc + 48.hours)
+      past_end_block = create(:user_block, :ends_at => Time.now.utc + 1.hour)
+      unread_past_end_block = create(:user_block, :needs_view, :ends_at => Time.now.utc + 1.hour)
+
+      travel 24.hours
+
+      assert_equal "active", block_short_status(future_end_block)
+      assert_equal "active", block_short_status(unread_future_end_block)
+      assert_equal "ended", block_short_status(past_end_block)
+      assert_equal "active until read", block_short_status(unread_past_end_block)
+    end
+  end
+
+  def test_block_short_status_with_immediate_update
+    freeze_time do
+      block = UserBlock.new :user => create(:user),
+                            :creator => create(:moderator_user),
+                            :reason => "because",
+                            :created_at => Time.now.utc,
+                            :ends_at => Time.now.utc,
+                            :deactivates_at => Time.now.utc,
+                            :needs_view => false
+
+      travel 1.second
+
+      block.save
+
+      assert_equal "ended", block_short_status(block)
+    end
+  end
+
+  def test_block_short_status_read
+    freeze_time do
+      block = create(:user_block, :needs_view, :ends_at => Time.now.utc)
+
+      travel 24.hours
+
+      assert_equal "active until read", block_short_status(block)
+
+      block.update(:needs_view => false, :deactivates_at => Time.now.utc)
+
+      read_date = Time.now.utc.to_date.strftime
+      short_status_dom = Rails::Dom::Testing.html_document.parse(block_short_status(block))
+      assert_dom short_status_dom, ":root", :text => "read at #{read_date}"
+
+      travel 24.hours
+
+      block.update(:reason => "updated reason")
+
+      short_status_dom = Rails::Dom::Testing.html_document.parse(block_short_status(block))
+      assert_dom short_status_dom, ":root", :text => "read at #{read_date}"
+    end
+  end
+
   def test_block_duration_in_words
     words = block_duration_in_words(364.days)
     assert_equal "11 months", words
diff --git a/test/system/browse_test.rb b/test/system/browse_test.rb
new file mode 100644 (file)
index 0000000..15dc1cb
--- /dev/null
@@ -0,0 +1,13 @@
+require "application_system_test_case"
+
+class BrowseTest < ApplicationSystemTestCase
+  test "relation member nodes should be visible on the map when viewing relations" do
+    relation = create(:relation)
+    node = create(:node)
+    create(:relation_member, :relation => relation, :member => node)
+
+    visit relation_path(relation)
+
+    assert_selector "#map .leaflet-overlay-pane path"
+  end
+end
index 6a8fcde3da68f00a0e047c695bcf6d7d160ced81..840b1a4c87b98ec779422877c179df6448ae983c 100644 (file)
@@ -147,9 +147,25 @@ L.OSM.DataLayer = L.FeatureGroup.extend({
       ways = L.OSM.getWays(xml, nodes),
       relations = L.OSM.getRelations(xml, nodes, ways);
 
+    var wayNodes = {}
+    for (var i = 0; i < ways.length; i++) {
+      var way = ways[i];
+      for (var j = 0; j < way.nodes.length; j++) {
+        wayNodes[way.nodes[j].id] = true
+      }
+    }
+
+    var relationNodes = {}
+    for (var i = 0; i < relations.length; i++){
+      var relation = relations[i];
+      for (var j = 0; j < relation.members.length; j++) {
+        relationNodes[relation.members[j].id] = true
+      }
+    }
+
     for (var node_id in nodes) {
       var node = nodes[node_id];
-      if (this.interestingNode(node, ways, relations)) {
+      if (this.interestingNode(node, wayNodes, relationNodes)) {
         features.push(node);
       }
     }
@@ -176,23 +192,9 @@ L.OSM.DataLayer = L.FeatureGroup.extend({
     return false;
   },
 
-  interestingNode: function (node, ways, relations) {
-    var used = false;
-
-    for (var i = 0; i < ways.length; i++) {
-      if (ways[i].nodes.indexOf(node) >= 0) {
-        used = true;
-        break;
-      }
-    }
-
-    if (!used) {
-      return true;
-    }
-
-    for (var i = 0; i < relations.length; i++) {
-      if (relations[i].members.indexOf(node) >= 0)
-        return true;
+  interestingNode: function (node, wayNodes, relationNodes) {
+    if (!wayNodes[node.id] || relationNodes[node.id]) {
+      return true
     }
 
     for (var key in node.tags) {
@@ -309,7 +311,7 @@ L.Util.extend(L.OSM, {
         else // relation-way and relation-relation membership not implemented
           rel_object.members[j] = null;
       }
-
+      rel_object.members = rel_object.members.filter(i => i !== null && i !== undefined)
       result.push(rel_object);
     }