]> git.openstreetmap.org Git - rails.git/commitdiff
Merge remote-tracking branch 'upstream/pull/5452'
authorTom Hughes <tom@compton.nu>
Sat, 15 Feb 2025 11:15:25 +0000 (11:15 +0000)
committerTom Hughes <tom@compton.nu>
Sat, 15 Feb 2025 11:15:25 +0000 (11:15 +0000)
Gemfile.lock
app/assets/javascripts/index.js
app/assets/javascripts/index/history.js
app/assets/javascripts/index/layers/data.js
app/assets/javascripts/index/layers/notes.js
app/assets/javascripts/index/query.js
app/assets/javascripts/index/search.js
app/assets/javascripts/leaflet.map.js
app/controllers/api/notes_controller.rb
app/controllers/api_controller.rb
test/controllers/api/changesets_controller_test.rb

index 56fca7d7fa9a848ffc937ce39fadd0e91bc2f016..0ca767c00a12e851e429b91aa2bafc4f515be6f5 100644 (file)
@@ -91,8 +91,8 @@ GEM
     ast (2.4.2)
     autoprefixer-rails (10.4.19.0)
       execjs (~> 2)
-    aws-eventstream (1.3.0)
-    aws-partitions (1.1049.0)
+    aws-eventstream (1.3.1)
+    aws-partitions (1.1050.0)
     aws-sdk-core (3.218.1)
       aws-eventstream (~> 1, >= 1.3.0)
       aws-partitions (~> 1, >= 1.992.0)
@@ -102,7 +102,7 @@ GEM
     aws-sdk-kms (1.98.0)
       aws-sdk-core (~> 3, >= 3.216.0)
       aws-sigv4 (~> 1.5)
-    aws-sdk-s3 (1.180.0)
+    aws-sdk-s3 (1.181.0)
       aws-sdk-core (~> 3, >= 3.216.0)
       aws-sdk-kms (~> 1)
       aws-sigv4 (~> 1.5)
@@ -353,10 +353,11 @@ GEM
     language_server-protocol (3.17.0.4)
     libv8-node (18.19.0.0)
     libxml-ruby (5.0.3)
+    lint_roller (1.1.0)
     listen (3.9.0)
       rb-fsevent (~> 0.10, >= 0.10.3)
       rb-inotify (~> 0.9, >= 0.9.10)
-    logger (1.6.5)
+    logger (1.6.6)
     logstasher (2.1.5)
       activesupport (>= 5.2)
       request_store
@@ -553,9 +554,10 @@ GEM
     rouge (4.5.1)
     rtlcss (0.2.1)
       mini_racer (>= 0.6.3)
-    rubocop (1.71.2)
+    rubocop (1.72.0)
       json (~> 2.3)
-      language_server-protocol (>= 3.17.0)
+      language_server-protocol (~> 3.17.0.2)
+      lint_roller (~> 1.1.0)
       parallel (~> 1.10)
       parser (>= 3.3.0.2)
       rainbow (>= 2.2.2, < 4.0)
@@ -626,7 +628,7 @@ GEM
       actionpack (>= 6.1)
       activesupport (>= 6.1)
       sprockets (>= 3.0.0)
-    stringio (3.1.2)
+    stringio (3.1.3)
     strong_migrations (1.8.0)
       activerecord (>= 5.2)
     teaspoon (1.4.0)
index a94131443d410b06b557a08aa306b1b90084edcc..c3ee1e3bc9b47729faab64ad478d6a7818cbabb4 100644 (file)
@@ -41,19 +41,18 @@ $(document).ready(function () {
     $("#sidebar_content")
       .empty();
 
-    $.ajax({
-      url: content_path,
-      dataType: "html",
-      complete: function (xhr) {
+    fetch(content_path, { headers: { "accept": "text/html", "x-requested-with": "XMLHttpRequest" } })
+      .then(response => {
         $("#flash").empty();
         $("#sidebar_loader").removeClass("delayed-fade-in").hide();
 
-        var content = $(xhr.responseText);
+        const title = response.headers.get("X-Page-Title");
+        if (title) document.title = decodeURIComponent(title);
 
-        if (xhr.getResponseHeader("X-Page-Title")) {
-          var title = xhr.getResponseHeader("X-Page-Title");
-          document.title = decodeURIComponent(title);
-        }
+        return response.text();
+      })
+      .then(html => {
+        const content = $(html);
 
         $("head")
           .find("link[type=\"application/atom+xml\"]")
@@ -67,8 +66,7 @@ $(document).ready(function () {
         if (callback) {
           callback();
         }
-      }
-    });
+      });
   };
 
   var params = OSM.mapParams();
index 3c7101c7408095d3f45be0f6e0fa263cadfb39ba..52929018bbd60886c3e3528f4ccb4be0d04ed5c2 100644 (file)
@@ -56,24 +56,23 @@ OSM.History = function (map) {
   }
 
   function update() {
-    var data = { list: "1" };
+    const data = new URLSearchParams();
 
     if (window.location.pathname === "/history") {
-      data.bbox = map.getBounds().wrap().toBBoxString();
+      data.set("bbox", map.getBounds().wrap().toBBoxString());
       var feedLink = $("link[type=\"application/atom+xml\"]"),
           feedHref = feedLink.attr("href").split("?")[0];
-      feedLink.attr("href", feedHref + "?bbox=" + data.bbox);
+      feedLink.attr("href", feedHref + "?" + data);
     }
 
-    $.ajax({
-      url: window.location.pathname,
-      method: "GET",
-      data: data,
-      success: function (html) {
+    data.set("list", "1");
+
+    fetch(window.location.pathname + "?" + data)
+      .then(response => response.text())
+      .then(function (html) {
         displayFirstChangesets(html);
         updateMap();
-      }
-    });
+      });
   }
 
   function loadMore(e) {
index e6a7cc66684be0323361d21758156a9ee816ffb8..25dc66a28ffee9e0061856257f509224989bb523 100644 (file)
@@ -79,20 +79,27 @@ OSM.initializeDataLayer = function (map) {
 
   function getData() {
     var bounds = map.getBounds();
-    var url = "/api/" + OSM.API_VERSION + "/map?bbox=" + bounds.toBBoxString();
+    var url = "/api/" + OSM.API_VERSION + "/map.json?bbox=" + bounds.toBBoxString();
 
     /*
      * Modern browsers are quite happy showing far more than 100 features in
-     * the data browser, so increase the limit to 4000 by default.
+     * the data browser, so increase the limit to 4000.
      */
     const maxFeatures = 4000;
 
     if (dataLoader) dataLoader.abort();
 
-    dataLoader = $.ajax({
-      url: url,
-      dataType: "json",
-      success: function (data) {
+    dataLoader = new AbortController();
+    fetch(url, { signal: dataLoader.signal })
+      .then(response => {
+        if (response.ok) return response.json();
+        const status = response.statusText || response.status;
+        if (response.status !== 400) throw new Error(status);
+        return response.text().then(text => {
+          throw new Error(text || status);
+        });
+      })
+      .then(function (data) {
         dataLayer.clearLayers();
 
         var features = dataLayer.buildFeatures(data);
@@ -116,26 +123,15 @@ OSM.initializeDataLayer = function (map) {
         if (map._objectLayer) {
           map._objectLayer.bringToFront();
         }
+      })
+      .catch(function (error) {
+        if (error.name === "AbortError") return;
 
-        dataLoader = null;
-      },
-      error: function (XMLHttpRequest, textStatus) {
-        dataLoader = null;
-        if (textStatus === "abort") return;
-
-        function closeError() {
+        displayLoadError(error?.message, () => {
           $("#browse_status").empty();
-        }
-
-        if (XMLHttpRequest.status === 400 && XMLHttpRequest.responseText) {
-          displayLoadError(XMLHttpRequest.responseText, closeError);
-        } else if (XMLHttpRequest.statusText) {
-          displayLoadError(XMLHttpRequest.statusText, closeError);
-        } else {
-          displayLoadError(String(XMLHttpRequest.status), closeError);
-        }
-      }
-    });
+        });
+      })
+      .finally(() => dataLoader = null);
   }
 
   function onSelect(layer) {
index 1bc3714f0472af0e9c9bd43c5621dd6750b7ebdc..9aa1f203f5546a82a7e7788ee3c2ff9e3a54f01f 100644 (file)
@@ -75,10 +75,12 @@ OSM.initializeNotesLayer = function (map) {
 
       if (noteLoader) noteLoader.abort();
 
-      noteLoader = $.ajax({
-        url: url,
-        success: success
-      });
+      noteLoader = new AbortController();
+      fetch(url, { signal: noteLoader.signal })
+        .then(response => response.json())
+        .then(success)
+        .catch(() => {})
+        .finally(() => noteLoader = null);
     }
 
     function success(json) {
@@ -93,8 +95,6 @@ OSM.initializeNotesLayer = function (map) {
       for (var id in oldNotes) {
         noteLayer.removeLayer(oldNotes[id]);
       }
-
-      noteLoader = null;
     }
   }
 };
index 54d5e080fb0f5675a968bcd720f9a0373ae5e23c..3673da5db85838b2b72b6bf6667e9196a6124562 100644 (file)
@@ -157,16 +157,17 @@ OSM.Query = function (map) {
       $section.data("ajax").abort();
     }
 
-    $section.data("ajax", $.ajax({
-      url: url,
+    $section.data("ajax", new AbortController());
+    fetch(url, {
       method: "POST",
-      data: {
+      body: new URLSearchParams({
         data: "[timeout:10][out:json];" + query
-      },
-      xhrFields: {
-        withCredentials: credentials
-      },
-      success: function (results) {
+      }),
+      credentials: credentials ? "include" : "same-origin",
+      signal: $section.data("ajax").signal
+    })
+      .then(response => response.json())
+      .then(function (results) {
         var elements;
 
         $section.find(".loader").hide();
@@ -221,16 +222,17 @@ OSM.Query = function (map) {
             .text(I18n.t("javascripts.query.nothing_found"))
             .appendTo($ul);
         }
-      },
-      error: function (xhr, status, error) {
+      })
+      .catch(function (error) {
+        if (error.name === "AbortError") return;
+
         $section.find(".loader").hide();
 
         $("<li>")
           .addClass("list-group-item")
-          .text(I18n.t("javascripts.query." + status, { server: url, error: error }))
+          .text(I18n.t("javascripts.query.error", { server: url, error: error.message }))
           .appendTo($ul);
-      }
-    }));
+      });
   }
 
   function compareSize(feature1, feature2) {
index 23af46145b0ae9295870bce53e778a31a93d87de..3c1af5056ad57b06b4d615c5788000ca9262d861 100644 (file)
@@ -47,21 +47,19 @@ OSM.Search = function (map) {
     var div = $(this).parents(".search_more"),
         csrf_param = $("meta[name=csrf-param]").attr("content"),
         csrf_token = $("meta[name=csrf-token]").attr("content"),
-        params = {};
+        params = new URLSearchParams();
 
     $(this).hide();
     div.find(".loader").show();
 
-    params[csrf_param] = csrf_token;
+    params.set(csrf_param, csrf_token);
 
-    $.ajax({
-      url: $(this).attr("href"),
+    fetch($(this).attr("href"), {
       method: "POST",
-      data: params,
-      success: function (data) {
-        div.replaceWith(data);
-      }
-    });
+      body: params
+    })
+      .then(response => response.text())
+      .then(data => div.replaceWith(data));
   }
 
   function showSearchResult() {
@@ -125,19 +123,20 @@ OSM.Search = function (map) {
       var entry = $(this),
           csrf_param = $("meta[name=csrf-param]").attr("content"),
           csrf_token = $("meta[name=csrf-token]").attr("content"),
-          params = {
+          params = new URLSearchParams({
             zoom: map.getZoom(),
             minlon: map.getBounds().getWest(),
             minlat: map.getBounds().getSouth(),
             maxlon: map.getBounds().getEast(),
             maxlat: map.getBounds().getNorth()
-          };
-      params[csrf_param] = csrf_token;
-      $.ajax({
-        url: entry.data("href"),
+          });
+      params.set(csrf_param, csrf_token);
+      fetch(entry.data("href"), {
         method: "POST",
-        data: params,
-        success: function (html) {
+        body: params
+      })
+        .then(response => response.text())
+        .then(function (html) {
           entry.html(html);
           // go to first result of first geocoder
           if (index === 0) {
@@ -146,8 +145,7 @@ OSM.Search = function (map) {
               panToSearchResult(firstResult.data());
             }
           }
-        }
-      });
+        });
     });
 
     return map.getState();
index 1324532d3bb592d8272e5d5b6bcce302603899a8..b101017219c12b64f19e522005fa19bdd291e4ba 100644 (file)
@@ -265,9 +265,7 @@ L.OSM.Map = L.Map.extend({
     this.removeObject();
 
     if (object.type === "note" || object.type === "changeset") {
-      this._objectLoader = {
-        abort: function () {}
-      };
+      this._objectLoader = { abort: () => {} };
 
       this._object = object;
       this._objectLayer = L.featureGroup().addTo(this);
@@ -295,10 +293,13 @@ L.OSM.Map = L.Map.extend({
       this.fire("overlayadd", { layer: this._objectLayer });
     } else { // element handled by L.OSM.DataLayer
       var map = this;
-      this._objectLoader = $.ajax({
-        url: OSM.apiUrl(object),
-        dataType: "json",
-        success: function (data) {
+      this._objectLoader = new AbortController();
+      fetch(OSM.apiUrl(object), {
+        headers: { accept: "application/json" },
+        signal: this._objectLoader.signal
+      })
+        .then(response => response.json())
+        .then(function (data) {
           map._object = object;
 
           map._objectLayer = new L.OSM.DataLayer(null, {
@@ -320,8 +321,8 @@ L.OSM.Map = L.Map.extend({
 
           if (callback) callback(map._objectLayer.getBounds());
           map.fire("overlayadd", { layer: map._objectLayer });
-        }
-      });
+        })
+        .catch(() => {});
     }
   },
 
index bc4d2eaf2ceaa47076e57e4182fdcca583d65809..a0095d954b5d6f48dd891560d11c7f755523c964 100644 (file)
@@ -387,7 +387,7 @@ module Api
     ##
     # Get author's information (for logged in users - user_id, for logged out users - IP address)
     def author_info
-      if scope_enabled?(:write_notes)
+      if current_user
         { :user_id => current_user.id }
       else
         { :user_ip => request.remote_ip }
index acf64c6e2533054a00aca83c64ee805435ad1049..9b2ee9b532ace14bbc30ed2c90083ff5a2b9fef9 100644 (file)
@@ -82,8 +82,6 @@ class ApiController < ApplicationController
     if doorkeeper_token
       set_locale
       report_error t("oauth.permissions.missing"), :forbidden
-    elsif current_user
-      head :forbidden
     else
       head :unauthorized
     end
index 39b1f3cf81d26773d27c3a9d4dd8183b615bb8a9..3e2d7e6ad8222786cb609571e46e94b85973de2d 100644 (file)
@@ -358,19 +358,8 @@ module Api
 
     def test_show_tag_and_discussion_json
       changeset = create(:changeset, :closed)
-
-      tag1 = ChangesetTag.new
-      tag1.changeset_id = changeset.id
-      tag1.k = "created_by"
-      tag1.v = "JOSM/1.5 (18364)"
-
-      tag2 = ChangesetTag.new
-      tag2.changeset_id = changeset.id
-      tag2.k = "comment"
-      tag2.v = "changeset comment"
-
-      changeset.changeset_tags = [tag1, tag2]
-
+      create(:changeset_tag, :changeset => changeset, :k => "created_by", :v => "JOSM/1.5 (18364)")
+      create(:changeset_tag, :changeset => changeset, :k => "comment", :v => "changeset comment")
       create_list(:changeset_comment, 3, :changeset_id => changeset.id)
 
       get changeset_show_path(changeset), :params => { :format => "json", :include_discussion => true }