From: Andy Allan Date: Wed, 15 Jan 2025 12:49:34 +0000 (+0000) Subject: Merge pull request #5449 from AntonKhorev/edit-preferences X-Git-Tag: live~630 X-Git-Url: https://git.openstreetmap.org/rails.git/commitdiff_plain/b8a1a904c6273252c56998178b69f5f65d744d69?hp=967e6d4d868b1916ef88d51d6b19a5d9001782f1 Merge pull request #5449 from AntonKhorev/edit-preferences Make preferences page editable without clicking 'Edit Preferences' --- diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 071abc44c..b3379b91a 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -27,6 +27,8 @@ FactoryBot/ExcessiveCreateList: - 'test/controllers/notes_controller_test.rb' - 'test/controllers/traces_controller_test.rb' - 'test/controllers/user_blocks_controller_test.rb' + - 'test/controllers/users/issued_blocks_controller_test.rb' + - 'test/controllers/users/received_blocks_controller_test.rb' - 'test/system/users_test.rb' # Offense count: 635 @@ -50,7 +52,6 @@ Lint/AssignmentInCondition: - 'app/helpers/application_helper.rb' - 'app/helpers/browse_tags_helper.rb' - 'app/mailers/user_mailer.rb' - - 'app/models/client_application.rb' - 'lib/nominatim.rb' - 'lib/osm.rb' - 'script/deliver-message' diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e298c944f..aea8b30b9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,7 +20,7 @@ development to check that your code matches our guidelines: ``` bundle exec rubocop bundle exec rails eslint -bundle exec erblint . +bundle exec erb_lint . ``` You can also install hooks to have git run checks automatically when diff --git a/Gemfile b/Gemfile index 277346b83..60a8fcace 100644 --- a/Gemfile +++ b/Gemfile @@ -55,6 +55,7 @@ gem "bootstrap_form", "~> 5.0" gem "cancancan" gem "config" gem "delayed_job_active_record" +gem "dry-schema", "< 1.14.0" # see https://github.com/openstreetmap/openstreetmap-website/issues/5482 gem "dry-validation" gem "frozen_record" gem "http_accept_language", "~> 2.1.1" diff --git a/Gemfile.lock b/Gemfile.lock index ab8d9f9d1..475ef50c4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -92,8 +92,8 @@ GEM autoprefixer-rails (10.4.19.0) execjs (~> 2) aws-eventstream (1.3.0) - aws-partitions (1.1026.0) - aws-sdk-core (3.214.0) + aws-partitions (1.1036.0) + aws-sdk-core (3.215.0) aws-eventstream (~> 1, >= 1.3.0) aws-partitions (~> 1, >= 1.992.0) aws-sigv4 (~> 1.9) @@ -101,11 +101,11 @@ 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) - aws-sigv4 (1.10.1) + aws-sigv4 (1.11.0) aws-eventstream (~> 1, >= 1.0.2) base64 (0.2.0) benchmark (0.4.0) @@ -120,7 +120,7 @@ GEM erubi (~> 1.4) parser (>= 2.4) smart_properties - bigdecimal (3.1.8) + bigdecimal (3.1.9) binding_of_caller (1.0.1) debug_inspector (>= 1.2.0) bootsnap (1.18.4) @@ -131,7 +131,7 @@ GEM bootstrap_form (5.4.0) actionpack (>= 6.1) activemodel (>= 6.1) - brakeman (6.2.2) + brakeman (7.0.0) racc brotli (0.6.0) browser (5.3.1) @@ -162,7 +162,7 @@ GEM config (5.5.2) deep_merge (~> 1.2, >= 1.2.1) ostruct - connection_pool (2.4.1) + connection_pool (2.5.0) cork (0.3.0) colored2 (~> 3.1) crack (1.0.0) @@ -216,18 +216,19 @@ 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) concurrent-ruby (~> 1.0) @@ -237,7 +238,7 @@ GEM dry-logic (>= 1.4, < 2) dry-types (>= 1.7, < 2) zeitwerk (~> 2.6) - dry-types (1.7.2) + dry-types (1.8.0) bigdecimal (~> 3.0) concurrent-ruby (~> 1.0) dry-core (~> 1.0) @@ -250,7 +251,7 @@ GEM dry-initializer (~> 3.0) dry-schema (>= 1.12, < 2) zeitwerk (~> 2.6) - erb_lint (0.7.0) + erb_lint (0.8.0) activesupport better_html (>= 2.0.1) parser (>= 2.7.1.4) @@ -259,7 +260,7 @@ GEM smart_properties erubi (1.13.1) execjs (2.10.0) - exifr (1.4.0) + exifr (1.4.1) factory_bot (6.5.0) activesupport (>= 5.0.0) factory_bot_rails (6.4.4) @@ -273,7 +274,7 @@ GEM faraday (>= 0.8) faraday-net_http (3.4.0) net-http (>= 0.5.0) - ffi (1.17.0) + ffi (1.17.1) ffi-compiler (1.3.2) ffi (>= 1.15.5) rake @@ -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) @@ -340,7 +341,7 @@ GEM railties (>= 4.2.0) thor (>= 0.14, < 2.0) json (2.9.1) - jwt (2.9.3) + jwt (2.10.1) base64 kgio (2.11.4) kramdown (2.5.1) @@ -353,11 +354,11 @@ GEM listen (3.9.0) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) - logger (1.6.4) + logger (1.6.5) 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.2) + net-imap (0.5.5) date net-protocol net-pop (0.1.2) @@ -393,7 +394,7 @@ GEM net-smtp (0.5.0) net-protocol nio4r (2.7.4) - nokogiri (1.17.2) + nokogiri (1.18.1) mini_portile2 (~> 2.8.2) racc (~> 1.4) oauth (1.1.0) @@ -481,7 +482,7 @@ GEM rack (~> 2.2, >= 2.2.4) rack-session (1.0.2) rack (< 3) - rack-test (2.1.0) + rack-test (2.2.0) rack (>= 1.3) rack-uri_sanitizer (0.0.2) rackup (1.0.1) @@ -531,10 +532,10 @@ 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.9.3) + regexp_parser (2.10.0) reline (0.6.0) io-console (~> 0.5) request_store (1.7.0) @@ -545,7 +546,7 @@ GEM rouge (4.5.1) rtlcss (0.2.1) mini_racer (>= 0.6.3) - rubocop (1.69.2) + rubocop (1.70.0) json (~> 2.3) language_server-protocol (>= 3.17.0) parallel (~> 1.10) @@ -564,10 +565,10 @@ 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.27.0) + rubocop-rails (2.28.0) activesupport (>= 4.2.0) rack (>= 1.1) rubocop (>= 1.52.0, < 2.0) @@ -579,10 +580,10 @@ GEM ruby-vips (2.2.2) ffi (~> 1.12) logger - rubyzip (2.3.2) - sanitize (6.1.3) + rubyzip (2.4.1) + sanitize (7.0.0) crass (~> 1.0.2) - nokogiri (>= 1.12.0) + nokogiri (>= 1.16.8) sass-embedded (1.64.2) google-protobuf (~> 3.23) rake (>= 13.0.0) @@ -630,7 +631,7 @@ GEM terser (1.2.4) execjs (>= 0.3.0, < 3) thor (1.3.2) - tilt (2.4.0) + tilt (2.6.0) timeout (0.4.3) turbo-rails (2.0.11) actionpack (>= 6.0.0) @@ -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) @@ -694,6 +696,7 @@ DEPENDENCIES doorkeeper doorkeeper-i18n doorkeeper-openid_connect + dry-schema (< 1.14.0) dry-validation erb_lint factory_bot_rails diff --git a/app/abilities/ability.rb b/app/abilities/ability.rb index e4b9dcf6b..9516a3012 100644 --- a/app/abilities/ability.rb +++ b/app/abilities/ability.rb @@ -23,8 +23,9 @@ class Ability can :read, Redaction can [:create, :destroy], :session can [:read, :data, :georss], Trace - can [:read, :terms, :create, :save, :suspended, :auth_success, :auth_failure], User - can [:read, :blocks_on, :blocks_by], UserBlock + can [:read, :create, :suspended, :auth_success, :auth_failure], User + can [:read, :update], :account_terms + can :read, UserBlock end if user&.active? @@ -42,7 +43,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 @@ -56,7 +57,7 @@ class Ability can [:read, :resolve, :ignore, :reopen], Issue can :create, IssueComment can [:create, :update, :destroy], Redaction - can [:create, :revoke_all], UserBlock + can [:create, :destroy], UserBlock can :update, UserBlock, :creator => user can :update, UserBlock, :revoker => user can :update, UserBlock, :active? => true diff --git a/app/assets/javascripts/diary_entry.js b/app/assets/javascripts/diary_entry.js index 625d43a52..bd5fd4dd6 100644 --- a/app/assets/javascripts/diary_entry.js +++ b/app/assets/javascripts/diary_entry.js @@ -2,8 +2,10 @@ $(document).ready(function () { var marker, map; function setLocation(e) { - $("#latitude").val(e.latlng.lat); - $("#longitude").val(e.latlng.lng); + const latlng = e.latlng.wrap(); + + $("#latitude").val(latlng.lat); + $("#longitude").val(latlng.lng); if (marker) { map.removeLayer(marker); diff --git a/app/assets/javascripts/index/changeset.js b/app/assets/javascripts/index/changeset.js index 75a1f7b4d..caf40f6b6 100644 --- a/app/assets/javascripts/index/changeset.js +++ b/app/assets/javascripts/index/changeset.js @@ -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; diff --git a/app/assets/javascripts/index/history.js b/app/assets/javascripts/index/history.js index c6ba0c2ed..ae8f027ed 100644 --- a/app/assets/javascripts/index/history.js +++ b/app/assets/javascripts/index/history.js @@ -164,6 +164,7 @@ OSM.History = function (map) { page.unload = function () { map.removeLayer(group); map.off("moveend", update); + map.off("zoomend", updateBounds); }; return page; diff --git a/app/assets/javascripts/index/new_note.js b/app/assets/javascripts/index/new_note.js index 887ba043b..4f38f8b55 100644 --- a/app/assets/javascripts/index/new_note.js +++ b/app/assets/javascripts/index/new_note.js @@ -5,7 +5,7 @@ OSM.NewNote = function (map) { content = $("#sidebar_content"), page = {}, addNoteButton = $(".control-note .control-button"), - newNote, + newNoteMarker, halo; var noteIcons = { @@ -35,39 +35,21 @@ OSM.NewNote = function (map) { OSM.router.route("/note/new"); }); - function createNote(marker, form, url) { - var location = marker.getLatLng().wrap(); - - marker.options.draggable = false; - marker.dragging.disable(); - - $(form).find("input[type=submit]").prop("disabled", true); - + function createNote(location, text, callback) { $.ajax({ - url: url, + url: "/api/0.6/notes.json", type: "POST", oauth: true, data: { lat: location.lat, lon: location.lng, - text: $(form.text).val() + text }, - success: function (feature) { - noteCreated(feature, marker); - } + success: callback }); - - function noteCreated(feature, marker) { - content.find("textarea").val(""); - updateMarker(feature); - newNote = null; - noteLayer.removeLayer(marker); - addNoteButton.removeClass("active"); - OSM.router.route("/note/" + feature.properties.id); - } } - function updateMarker(feature) { + function addCreatedNoteMarker(feature) { var marker = L.marker(feature.geometry.coordinates.reverse(), { icon: noteIcons[feature.properties.status], opacity: 0.9, @@ -75,38 +57,78 @@ OSM.NewNote = function (map) { }); marker.id = feature.properties.id; marker.addTo(noteLayer); - return marker; } - page.pushstate = page.popstate = function (path) { - OSM.loadSidebarContent(path, function () { - page.load(path); + function addHalo(latlng) { + if (halo) map.removeLayer(halo); + + halo = L.circleMarker(latlng, { + weight: 2.5, + radius: 20, + fillOpacity: 0.5, + color: "#FF6200" }); - }; - function newHalo(loc, a) { - var hasHalo = halo && map.hasLayer(halo); + map.addLayer(halo); + } - if (a === "dragstart" && hasHalo) { - map.removeLayer(halo); - } else { - if (hasHalo) map.removeLayer(halo); + function removeHalo() { + if (halo) map.removeLayer(halo); + halo = null; + } - halo = L.circleMarker(loc, { - weight: 2.5, - radius: 20, - fillOpacity: 0.5, - color: "#FF6200" - }); + function addNewNoteMarker(latlng) { + if (newNoteMarker) map.removeLayer(newNoteMarker); - map.addLayer(halo); - } + newNoteMarker = L.marker(latlng, { + icon: noteIcons.new, + opacity: 0.9, + draggable: true + }); + + newNoteMarker.on("dragstart dragend", function (a) { + removeHalo(); + if (a.type === "dragend") { + addHalo(newNoteMarker.getLatLng()); + } + }); + + newNoteMarker.addTo(map); + addHalo(newNoteMarker.getLatLng()); + + newNoteMarker.on("dragend", function () { + content.find("textarea").focus(); + }); } - page.load = function (path) { - if (addNoteButton.hasClass("disabled")) return; - if (addNoteButton.hasClass("active")) return; + function removeNewNoteMarker() { + removeHalo(); + if (newNoteMarker) map.removeLayer(newNoteMarker); + newNoteMarker = null; + } + + function moveNewNotMarkerToClick(e) { + if (newNoteMarker) newNoteMarker.setLatLng(e.latlng); + if (halo) halo.setLatLng(e.latlng); + content.find("textarea").focus(); + } + + function updateControls() { + const zoomedOut = addNoteButton.hasClass("disabled"); + const withoutText = content.find("textarea").val() === ""; + content.find("#new-note-zoom-warning").prop("hidden", !zoomedOut); + content.find("input[type=submit]").prop("disabled", zoomedOut || withoutText); + if (newNoteMarker) newNoteMarker.setOpacity(zoomedOut ? 0.5 : 0.9); + } + + page.pushstate = page.popstate = function (path) { + OSM.loadSidebarContent(path, function () { + page.load(path); + }); + }; + + page.load = function (path) { addNoteButton.addClass("active"); map.addLayer(noteLayer); @@ -124,44 +146,43 @@ OSM.NewNote = function (map) { padding: [50, 50] }); - newNote = L.marker(markerLatlng, { - icon: noteIcons.new, - opacity: 0.9, - draggable: true - }); - - newNote.on("dragstart dragend", function (a) { - newHalo(newNote.getLatLng(), a.type); - }); - - newNote.addTo(noteLayer); - newHalo(newNote.getLatLng()); - - newNote.on("remove", function () { - addNoteButton.removeClass("active"); - }).on("dragend", function () { - content.find("textarea").focus(); - }); + addNewNoteMarker(markerLatlng); content.find("textarea") - .on("input", disableWhenBlank) + .on("input", updateControls) .focus(); - function disableWhenBlank(e) { - $(e.target.form.add).prop("disabled", $(e.target).val() === ""); - } - content.find("input[type=submit]").on("click", function (e) { + const location = newNoteMarker.getLatLng().wrap(); + const text = content.find("textarea").val(); + e.preventDefault(); - createNote(newNote, e.target.form, "/api/0.6/notes.json"); + $(this).prop("disabled", true); + newNoteMarker.options.draggable = false; + newNoteMarker.dragging.disable(); + + createNote(location, text, (feature) => { + if (typeof OSM.user === "undefined") { + var anonymousNotesCount = Number(Cookies.get("_osm_anonymous_notes_count")) || 0; + Cookies.set("_osm_anonymous_notes_count", anonymousNotesCount + 1, { secure: true, expires: 30, path: "/", samesite: "lax" }); + } + content.find("textarea").val(""); + addCreatedNoteMarker(feature); + OSM.router.route("/note/" + feature.properties.id); + }); }); + map.on("click", moveNewNotMarkerToClick); + addNoteButton.on("disabled enabled", updateControls); + updateControls(); + return map.getState(); }; page.unload = function () { - if (newNote) noteLayer.removeLayer(newNote); - if (halo) map.removeLayer(halo); + map.off("click", moveNewNotMarkerToClick); + addNoteButton.off("disabled enabled", updateControls); + removeNewNoteMarker(); addNoteButton.removeClass("active"); }; diff --git a/app/assets/javascripts/leaflet.map.js b/app/assets/javascripts/leaflet.map.js index 6537b0b23..e0c2ee60b 100644 --- a/app/assets/javascripts/leaflet.map.js +++ b/app/assets/javascripts/leaflet.map.js @@ -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; } diff --git a/app/assets/javascripts/leaflet.note.js b/app/assets/javascripts/leaflet.note.js index 5f8010967..19fc9392c 100644 --- a/app/assets/javascripts/leaflet.note.js +++ b/app/assets/javascripts/leaflet.note.js @@ -14,12 +14,19 @@ L.OSM.note = function (options) { map.on("zoomend", update); function update() { - var disabled = OSM.STATUS === "database_offline" || map.getZoom() < 12; + var wasDisabled = link.hasClass("disabled"), + isDisabled = OSM.STATUS === "database_offline" || map.getZoom() < 12; link - .toggleClass("disabled", disabled) - .attr("data-bs-original-title", I18n.t(disabled ? + .toggleClass("disabled", isDisabled) + .attr("data-bs-original-title", I18n.t(isDisabled ? "javascripts.site.createnote_disabled_tooltip" : "javascripts.site.createnote_tooltip")); + + if (isDisabled && !wasDisabled) { + link.trigger("disabled"); + } else if (wasDisabled && !isDisabled) { + link.trigger("enabled"); + } } update(); diff --git a/app/assets/stylesheets/common.scss b/app/assets/stylesheets/common.scss index 323f60e08..9ce6aec34 100644 --- a/app/assets/stylesheets/common.scss +++ b/app/assets/stylesheets/common.scss @@ -818,7 +818,7 @@ tr.turn { /* Rules for the account confirmation page */ -.users-terms { +.accounts-terms-show { .legale { padding: $lineheight; margin-bottom: $lineheight; diff --git a/app/controllers/account/deletions_controller.rb b/app/controllers/accounts/deletions_controller.rb similarity index 92% rename from app/controllers/account/deletions_controller.rb rename to app/controllers/accounts/deletions_controller.rb index 2e3c777fa..303da6cfb 100644 --- a/app/controllers/account/deletions_controller.rb +++ b/app/controllers/accounts/deletions_controller.rb @@ -1,4 +1,4 @@ -module Account +module Accounts class DeletionsController < ApplicationController layout "site" diff --git a/app/controllers/accounts/terms_controller.rb b/app/controllers/accounts/terms_controller.rb new file mode 100644 index 000000000..0513a031c --- /dev/null +++ b/app/controllers/accounts/terms_controller.rb @@ -0,0 +1,65 @@ +module Accounts + class TermsController < ApplicationController + include SessionMethods + + layout "site" + + before_action :disable_terms_redirect + before_action :authorize_web + before_action :set_locale + before_action :check_database_readable + + authorize_resource :class => :account_terms + + def show + @legale = params[:legale] || OSM.ip_to_country(request.remote_ip) || Settings.default_legale + @text = OSM.legal_text_for_country(@legale) + + if request.xhr? + render :partial => "terms" + else + @title = t ".title" + + if current_user&.terms_agreed? + # Already agreed to terms, so just show settings + redirect_to edit_account_path + elsif current_user.nil? + redirect_to login_path(:referer => request.fullpath) + end + end + end + + def update + @title = t "users.new.title" + + if params[:decline] || !(params[:read_tou] && params[:read_ct]) + if current_user + current_user.terms_seen = true + + flash[:notice] = { :partial => "accounts/terms/terms_declined_flash" } if current_user.save + + referer = safe_referer(params[:referer]) if params[:referer] + + redirect_to referer || edit_account_path + elsif params[:decline] + redirect_to t("users.terms.declined"), :allow_other_host => true + else + redirect_to account_terms_path + end + elsif current_user + unless current_user.terms_agreed? + current_user.consider_pd = params[:user][:consider_pd] + current_user.tou_agreed = Time.now.utc + current_user.terms_agreed = Time.now.utc + current_user.terms_seen = true + + flash[:notice] = t "users.new.terms accepted" if current_user.save + end + + referer = safe_referer(params[:referer]) if params[:referer] + + redirect_to referer || edit_account_path + end + end + end +end diff --git a/app/controllers/api/messages_controller.rb b/app/controllers/api/messages_controller.rb index cbbd8539c..ea5abe8df 100644 --- a/app/controllers/api/messages_controller.rb +++ b/app/controllers/api/messages_controller.rb @@ -5,7 +5,6 @@ module Api before_action :authorize before_action :check_api_writable, :only => [:create, :update, :destroy] - before_action :check_api_readable, :except => [:create, :update, :destroy] authorize_resource diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 32b53bad7..f6006fe5e 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -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 @@ -56,11 +56,11 @@ class ApplicationController < ActionController::Base # don't allow access to any auth-requiring part of the site unless # the new CTs have been seen (and accept/decline chosen). elsif !current_user.terms_seen && flash[:skip_terms].nil? - flash[:notice] = t "users.terms.you need to accept or decline" + flash[:notice] = t "accounts.terms.show.you need to accept or decline" if params[:referer] - redirect_to :controller => "users", :action => "terms", :referer => params[:referer] + redirect_to account_terms_path(:referer => params[:referer]) else - redirect_to :controller => "users", :action => "terms", :referer => request.fullpath + redirect_to account_terms_path(:referer => request.fullpath) end end end @@ -114,7 +114,7 @@ class ApplicationController < ActionController::Base def check_database_writable(need_api: false) if Settings.status == "database_offline" || Settings.status == "database_readonly" || - (need_api && (Settings.status == "api_offline" || Settings.status == "api_readonly")) + (need_api && %w[api_offline api_readonly].include?(Settings.status)) if request.xhr? report_error "Database offline for maintenance", :service_unavailable else @@ -339,7 +339,7 @@ class ApplicationController < ActionController::Base begin referer = URI.parse(referer) - if referer.scheme == "http" || referer.scheme == "https" + if %w[http https].include?(referer.scheme) referer.scheme = nil referer.host = nil referer.port = nil diff --git a/app/controllers/concerns/session_methods.rb b/app/controllers/concerns/session_methods.rb index 45cf0d943..4bbfac34f 100644 --- a/app/controllers/concerns/session_methods.rb +++ b/app/controllers/concerns/session_methods.rb @@ -39,6 +39,8 @@ module SessionMethods session[:fingerprint] = user.fingerprint session_expires_after 28.days if session[:remember_me] + cookies.delete :_osm_anonymous_notes_count + target = referer || url_for(:controller => :site, :action => :index) # The user is logged in, so decide where to send them: @@ -48,7 +50,7 @@ module SessionMethods # - If they were referred to the login, send them back there. # - Otherwise, send them to the home page. if !user.terms_seen - redirect_to :controller => :users, :action => :terms, :referer => target + redirect_to account_terms_path(:referer => target) elsif user.blocked_on_view redirect_to user.blocked_on_view, :referer => target else diff --git a/app/controllers/confirmations_controller.rb b/app/controllers/confirmations_controller.rb index 7bbb3a093..72c1955e0 100644 --- a/app/controllers/confirmations_controller.rb +++ b/app/controllers/confirmations_controller.rb @@ -30,6 +30,7 @@ class ConfirmationsController < ApplicationController user.email_valid = true flash[:notice] = gravatar_status_message(user) if gravatar_enable(user) user.save! + cookies.delete :_osm_anonymous_notes_count referer = safe_referer(params[:referer]) if params[:referer] pending_user = session.delete(:pending_user) diff --git a/app/controllers/diary_comments_controller.rb b/app/controllers/diary_comments_controller.rb index f6597cf4c..676bc22a6 100644 --- a/app/controllers/diary_comments_controller.rb +++ b/app/controllers/diary_comments_controller.rb @@ -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/diary_entries_controller.rb b/app/controllers/diary_entries_controller.rb index 760c9a301..27099cd9c 100644 --- a/app/controllers/diary_entries_controller.rb +++ b/app/controllers/diary_entries_controller.rb @@ -123,7 +123,7 @@ class DiaryEntriesController < ApplicationController # Subscribe user to diary comments @diary_entry.subscriptions.create(:user => current_user) - redirect_to :action => "index", :display_name => current_user.display_name + redirect_to diary_entry_path(@diary_entry.user, @diary_entry) else render :action => "new" end diff --git a/app/controllers/elements_controller.rb b/app/controllers/elements_controller.rb new file mode 100644 index 000000000..99c8afe3b --- /dev/null +++ b/app/controllers/elements_controller.rb @@ -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/geocoder_controller.rb b/app/controllers/geocoder_controller.rb index 43f276efa..85b4476f6 100644 --- a/app/controllers/geocoder_controller.rb +++ b/app/controllers/geocoder_controller.rb @@ -101,8 +101,9 @@ class GeocoderController < ApplicationController if klass == "boundary" && type == "administrative" rank = (place.attributes["address_rank"].to_i + 1) / 2 prefix_name = t "geocoder.search_osm_nominatim.admin_levels.level#{rank}", :default => prefix_name + place_tags = %w[linked_place place] place.elements["extratags"].elements.each("tag") do |extratag| - prefix_name = t "geocoder.search_osm_nominatim.prefix.place.#{extratag.attributes['value']}", :default => prefix_name if extratag.attributes["key"] == "linked_place" || extratag.attributes["key"] == "place" + prefix_name = t "geocoder.search_osm_nominatim.prefix.place.#{extratag.attributes['value']}", :default => prefix_name if place_tags.include?(extratag.attributes["key"]) end end prefix = t ".prefix_format", :name => prefix_name diff --git a/app/controllers/messages/inboxes_controller.rb b/app/controllers/messages/inboxes_controller.rb new file mode 100644 index 000000000..96ec27c26 --- /dev/null +++ b/app/controllers/messages/inboxes_controller.rb @@ -0,0 +1,8 @@ +module Messages + class InboxesController < MailboxesController + # Display the list of messages that have been sent to the user. + def show + @title = t ".title" + end + end +end diff --git a/app/controllers/messages/mailboxes_controller.rb b/app/controllers/messages/mailboxes_controller.rb new file mode 100644 index 000000000..a0da9f52b --- /dev/null +++ b/app/controllers/messages/mailboxes_controller.rb @@ -0,0 +1,12 @@ +module Messages + class MailboxesController < ApplicationController + layout "site" + + before_action :authorize_web + before_action :set_locale + + authorize_resource :class => Message + + before_action :check_database_readable + end +end diff --git a/app/controllers/messages/muted_inboxes_controller.rb b/app/controllers/messages/muted_inboxes_controller.rb new file mode 100644 index 000000000..2d025cc9a --- /dev/null +++ b/app/controllers/messages/muted_inboxes_controller.rb @@ -0,0 +1,10 @@ +module Messages + class MutedInboxesController < MailboxesController + # Display the list of muted messages received by the user. + def show + @title = t ".title" + + redirect_to messages_inbox_path if current_user.muted_messages.none? + end + end +end diff --git a/app/controllers/messages/outboxes_controller.rb b/app/controllers/messages/outboxes_controller.rb new file mode 100644 index 000000000..f4d0a509c --- /dev/null +++ b/app/controllers/messages/outboxes_controller.rb @@ -0,0 +1,8 @@ +module Messages + class OutboxesController < MailboxesController + # Display the list of messages that the user has sent to other users. + def show + @title = t ".title" + end + end +end diff --git a/app/controllers/messages/replies_controller.rb b/app/controllers/messages/replies_controller.rb new file mode 100644 index 000000000..b1e7b8d19 --- /dev/null +++ b/app/controllers/messages/replies_controller.rb @@ -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 diff --git a/app/controllers/messages_controller.rb b/app/controllers/messages_controller.rb index 7d86796b1..cc5f6c56d 100644 --- a/app/controllers/messages_controller.rb +++ b/app/controllers/messages_controller.rb @@ -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 :action => :inbox + redirect_to messages_outbox_path else @title = t "messages.new.title" render :action => "new" @@ -66,65 +66,13 @@ class MessagesController < ApplicationController referer = safe_referer(params[:referer]) if params[:referer] - redirect_to referer || { :action => :inbox }, :status => :see_other + redirect_to referer || messages_inbox_path, :status => :see_other end rescue ActiveRecord::RecordNotFound @title = t "messages.no_such_message.title" 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 - - # Display the list of messages that have been sent to the user. - def inbox - @title = t ".title" - end - - # Display the list of messages that the user has sent to other users. - def outbox - @title = t ".title" - end - - # Display the list of muted messages received by the user. - def muted - @title = t ".title" - - redirect_to inbox_messages_path if current_user.muted_messages.none? - end - # Set the message as being read or unread. def mark @message = current_user.messages.unscope(:where => :muted).find(params[:message_id]) @@ -139,9 +87,9 @@ class MessagesController < ApplicationController if @message.save flash[:notice] = notice if @message.muted? - redirect_to muted_messages_path, :status => :see_other + redirect_to messages_muted_inbox_path, :status => :see_other else - redirect_to inbox_messages_path, :status => :see_other + redirect_to messages_inbox_path, :status => :see_other end end rescue ActiveRecord::RecordNotFound @@ -160,9 +108,9 @@ class MessagesController < ApplicationController end if current_user.muted_messages.none? - redirect_to inbox_messages_path + redirect_to messages_inbox_path else - redirect_to muted_messages_path + redirect_to messages_muted_inbox_path end end diff --git a/app/controllers/nodes_controller.rb b/app/controllers/nodes_controller.rb index a05fa8cd2..0ef07dbbf 100644 --- a/app/controllers/nodes_controller.rb +++ b/app/controllers/nodes_controller.rb @@ -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/notes_controller.rb b/app/controllers/notes_controller.rb index c40e776b4..4b4f3d651 100644 --- a/app/controllers/notes_controller.rb +++ b/app/controllers/notes_controller.rb @@ -45,6 +45,7 @@ class NotesController < ApplicationController end def new + @anonymous_notes_count = request.cookies["_osm_anonymous_notes_count"].to_i || 0 render :action => :new_readonly if api_status != "online" end end diff --git a/app/controllers/old_elements_controller.rb b/app/controllers/old_elements_controller.rb new file mode 100644 index 000000000..02c999b36 --- /dev/null +++ b/app/controllers/old_elements_controller.rb @@ -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 diff --git a/app/controllers/old_nodes_controller.rb b/app/controllers/old_nodes_controller.rb index 596b57967..3b187e4ab 100644 --- a/app/controllers/old_nodes_controller.rb +++ b/app/controllers/old_nodes_controller.rb @@ -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 diff --git a/app/controllers/old_relations_controller.rb b/app/controllers/old_relations_controller.rb index d57cf25fe..ec256d6af 100644 --- a/app/controllers/old_relations_controller.rb +++ b/app/controllers/old_relations_controller.rb @@ -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 diff --git a/app/controllers/old_ways_controller.rb b/app/controllers/old_ways_controller.rb index de60de317..1b3ebd747 100644 --- a/app/controllers/old_ways_controller.rb +++ b/app/controllers/old_ways_controller.rb @@ -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 diff --git a/app/controllers/relations_controller.rb b/app/controllers/relations_controller.rb index 8aeefd6cc..9199c9e4a 100644 --- a/app/controllers/relations_controller.rb +++ b/app/controllers/relations_controller.rb @@ -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 diff --git a/app/controllers/site_controller.rb b/app/controllers/site_controller.rb index 58f0a11c9..9adbaa195 100644 --- a/app/controllers/site_controller.rb +++ b/app/controllers/site_controller.rb @@ -24,7 +24,7 @@ class SiteController < ApplicationController end def index - session[:location] ||= OSM.ip_location(request.env["REMOTE_ADDR"]) unless Settings.status == "database_readonly" || Settings.status == "database_offline" + session[:location] ||= OSM.ip_location(request.env["REMOTE_ADDR"]) unless %w[database_readonly database_offline].include?(Settings.status) end def permalink diff --git a/app/controllers/user_blocks_controller.rb b/app/controllers/user_blocks_controller.rb index 551371794..a526f529e 100644 --- a/app/controllers/user_blocks_controller.rb +++ b/app/controllers/user_blocks_controller.rb @@ -9,11 +9,11 @@ class UserBlocksController < ApplicationController authorize_resource - before_action :lookup_user, :only => [:new, :create, :revoke_all, :blocks_on, :blocks_by] + before_action :lookup_user, :only => [:new, :create] before_action :lookup_user_block, :only => [:show, :edit, :update] before_action :require_valid_params, :only => [:create, :update] before_action :check_database_readable - before_action :check_database_writable, :only => [:create, :update, :revoke_all] + before_action :check_database_writable, :only => [:create, :update] def index @params = params.permit @@ -105,46 +105,6 @@ class UserBlocksController < ApplicationController end end - ## - # revokes all active blocks - def revoke_all - if request.post? && params[:confirm] - @user.blocks.active.each { |block| block.revoke!(current_user) } - flash[:notice] = t ".flash" - redirect_to user_blocks_on_path(@user) - end - end - - ## - # shows a list of all the blocks on the given user - def blocks_on - @params = params.permit(:display_name) - - user_blocks = UserBlock.where(:user => @user) - - @user_blocks, @newer_user_blocks_id, @older_user_blocks_id = get_page_items(user_blocks, :includes => [:user, :creator, :revoker]) - - @show_user_name = false - @show_creator_name = true - - render :partial => "page" if turbo_frame_request_id == "pagination" - end - - ## - # shows a list of all the blocks by the given user. - def blocks_by - @params = params.permit(:display_name) - - user_blocks = UserBlock.where(:creator => @user) - - @user_blocks, @newer_user_blocks_id, @older_user_blocks_id = get_page_items(user_blocks, :includes => [:user, :creator, :revoker]) - - @show_user_name = true - @show_creator_name = false - - render :partial => "page" if turbo_frame_request_id == "pagination" - end - private ## diff --git a/app/controllers/users/issued_blocks_controller.rb b/app/controllers/users/issued_blocks_controller.rb new file mode 100644 index 000000000..b533b5f6d --- /dev/null +++ b/app/controllers/users/issued_blocks_controller.rb @@ -0,0 +1,31 @@ +module Users + class IssuedBlocksController < ApplicationController + include UserMethods + include PaginationMethods + + layout "site" + + before_action :authorize_web + before_action :set_locale + + authorize_resource :class => UserBlock + + before_action :lookup_user + before_action :check_database_readable + + ## + # shows a list of all the blocks by the given user. + def show + @params = params.permit(:user_display_name) + + user_blocks = UserBlock.where(:creator => @user) + + @user_blocks, @newer_user_blocks_id, @older_user_blocks_id = get_page_items(user_blocks, :includes => [:user, :creator, :revoker]) + + @show_user_name = true + @show_creator_name = false + + render :partial => "user_blocks/page" if turbo_frame_request_id == "pagination" + end + end +end diff --git a/app/controllers/users/received_blocks_controller.rb b/app/controllers/users/received_blocks_controller.rb new file mode 100644 index 000000000..6f6cabd26 --- /dev/null +++ b/app/controllers/users/received_blocks_controller.rb @@ -0,0 +1,48 @@ +module Users + class ReceivedBlocksController < ApplicationController + include UserMethods + include PaginationMethods + + layout "site" + + before_action :authorize_web + before_action :set_locale + + authorize_resource :class => UserBlock + + before_action :lookup_user + before_action :check_database_readable + before_action :check_database_writable, :only => :destroy + + ## + # shows a list of all the blocks on the given user + def show + @params = params.permit(:user_display_name) + + user_blocks = UserBlock.where(:user => @user) + + @user_blocks, @newer_user_blocks_id, @older_user_blocks_id = get_page_items(user_blocks, :includes => [:user, :creator, :revoker]) + + @show_user_name = false + @show_creator_name = true + + render :partial => "user_blocks/page" if turbo_frame_request_id == "pagination" + end + + ## + # shows revoke all active blocks page + def edit; end + + ## + # revokes all active blocks + def destroy + if params[:confirm] + @user.blocks.active.each { |block| block.revoke!(current_user) } + flash[:notice] = t ".flash" + redirect_to user_received_blocks_path(@user) + else + render :action => :edit + end + end + end +end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 471215c92..904b960a2 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -6,7 +6,6 @@ class UsersController < ApplicationController layout "site" skip_before_action :verify_authenticity_token, :only => [:auth_success] - before_action :disable_terms_redirect, :only => [:terms, :save] before_action :authorize_web before_action :set_locale before_action :check_database_readable @@ -77,7 +76,24 @@ class UsersController < ApplicationController render :action => "new" else # Save the user record - save_new_user params[:email_hmac], params[:referer] + if save_new_user params[:email_hmac] + SIGNUP_IP_LIMITER&.update(request.remote_ip) + SIGNUP_EMAIL_LIMITER&.update(canonical_email(current_user.email)) + + flash[:matomo_goal] = Settings.matomo["goals"]["signup"] if defined?(Settings.matomo) + + referer = welcome_path(welcome_options(params[:referer])) + + if current_user.status == "active" + successful_login(current_user, referer) + else + session[:pending_user] = current_user.id + UserMailer.signup_confirm(current_user, current_user.generate_token_for(:new_user), referer).deliver_later + redirect_to :controller => :confirmations, :action => :confirm, :display_name => current_user.display_name + end + else + render :action => "new", :referer => params[:referer] + end end end end @@ -89,57 +105,6 @@ class UsersController < ApplicationController redirect_to user_path(:display_name => params[:display_name]) end - def terms - @legale = params[:legale] || OSM.ip_to_country(request.remote_ip) || Settings.default_legale - @text = OSM.legal_text_for_country(@legale) - - if request.xhr? - render :partial => "terms" - else - @title = t ".title" - - if current_user&.terms_agreed? - # Already agreed to terms, so just show settings - redirect_to edit_account_path - elsif current_user.nil? - redirect_to login_path(:referer => request.fullpath) - end - end - end - - def save - @title = t "users.new.title" - - if params[:decline] || !(params[:read_tou] && params[:read_ct]) - if current_user - current_user.terms_seen = true - - flash[:notice] = { :partial => "users/terms_declined_flash" } if current_user.save - - referer = safe_referer(params[:referer]) if params[:referer] - - redirect_to referer || edit_account_path - elsif params[:decline] - redirect_to t("users.terms.declined"), :allow_other_host => true - else - redirect_to :action => :terms - end - elsif current_user - unless current_user.terms_agreed? - current_user.consider_pd = params[:user][:consider_pd] - current_user.tou_agreed = Time.now.utc - current_user.terms_agreed = Time.now.utc - current_user.terms_seen = true - - flash[:notice] = t "users.new.terms accepted" if current_user.save - end - - referer = safe_referer(params[:referer]) if params[:referer] - - redirect_to referer || edit_account_path - end - end - def go_public current_user.data_public = true current_user.save @@ -238,7 +203,7 @@ class UsersController < ApplicationController private - def save_new_user(email_hmac, referer = nil) + def save_new_user(email_hmac) current_user.data_public = true current_user.description = "" if current_user.description.nil? current_user.creation_address = request.remote_ip @@ -254,24 +219,7 @@ class UsersController < ApplicationController current_user.activate end - if current_user.save - SIGNUP_IP_LIMITER&.update(request.remote_ip) - SIGNUP_EMAIL_LIMITER&.update(canonical_email(current_user.email)) - - flash[:matomo_goal] = Settings.matomo["goals"]["signup"] if defined?(Settings.matomo) - - referer = welcome_path(welcome_options(referer)) - - if current_user.status == "active" - successful_login(current_user, referer) - else - session[:pending_user] = current_user.id - UserMailer.signup_confirm(current_user, current_user.generate_token_for(:new_user), referer).deliver_later - redirect_to :controller => :confirmations, :action => :confirm, :display_name => current_user.display_name - end - else - render :action => "new", :referer => params[:referer] - end + current_user.save end def welcome_options(referer = nil) diff --git a/app/controllers/ways_controller.rb b/app/controllers/ways_controller.rb index d4abe2db7..d5c5d8736 100644 --- a/app/controllers/ways_controller.rb +++ b/app/controllers/ways_controller.rb @@ -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 diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index fcf253289..ff6dcd2ff 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -37,7 +37,8 @@ module ApplicationHelper if content_for? :body_class content_for :body_class else - "#{params[:controller]} #{params[:controller]}-#{params[:action]}" + controller_part = params[:controller].tr("/", "-") + "#{controller_part} #{controller_part}-#{params[:action]}" end end diff --git a/app/helpers/changesets_helper.rb b/app/helpers/changesets_helper.rb index ae953c583..4605658f6 100644 --- a/app/helpers/changesets_helper.rb +++ b/app/helpers/changesets_helper.rb @@ -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 diff --git a/app/helpers/user_blocks_helper.rb b/app/helpers/user_blocks_helper.rb index 8a3a8a3eb..f18a6250c 100644 --- a/app/helpers/user_blocks_helper.rb +++ b/app/helpers/user_blocks_helper.rb @@ -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 diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index dee3dafbe..1dd13fb2d 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -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) diff --git a/app/models/trace.rb b/app/models/trace.rb index 20723b98d..4d71b4b29 100644 --- a/app/models/trace.rb +++ b/app/models/trace.rb @@ -86,11 +86,11 @@ class Trace < ApplicationRecord end def public? - visibility == "public" || visibility == "identifiable" + %w[public identifiable].include?(visibility) end def trackable? - visibility == "trackable" || visibility == "identifiable" + %w[trackable identifiable].include?(visibility) end def identifiable? diff --git a/app/views/account/deletions/show.html.erb b/app/views/accounts/deletions/show.html.erb similarity index 100% rename from app/views/account/deletions/show.html.erb rename to app/views/accounts/deletions/show.html.erb diff --git a/app/views/accounts/edit.html.erb b/app/views/accounts/edit.html.erb index a3e6f943b..16f109c9f 100644 --- a/app/views/accounts/edit.html.erb +++ b/app/views/accounts/edit.html.erb @@ -19,7 +19,11 @@
- <%= 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" }) %>
(" target="_new"><%= t ".openid.link text" %>) @@ -49,7 +53,7 @@ <% end %> <% else %> <%= t ".contributor terms.not yet agreed" %> - <%= link_to t(".contributor terms.review link text"), :controller => "users", :action => "terms" %> + <%= link_to t(".contributor terms.review link text"), account_terms_path %> <% end %> diff --git a/app/views/users/_terms.html.erb b/app/views/accounts/terms/_terms.html.erb similarity index 100% rename from app/views/users/_terms.html.erb rename to app/views/accounts/terms/_terms.html.erb diff --git a/app/views/users/_terms_declined_flash.html.erb b/app/views/accounts/terms/_terms_declined_flash.html.erb similarity index 100% rename from app/views/users/_terms_declined_flash.html.erb rename to app/views/accounts/terms/_terms_declined_flash.html.erb diff --git a/app/views/users/terms.html.erb b/app/views/accounts/terms/show.html.erb similarity index 98% rename from app/views/users/terms.html.erb rename to app/views/accounts/terms/show.html.erb index a5dc3291d..3cc52302f 100644 --- a/app/views/users/terms.html.erb +++ b/app/views/accounts/terms/show.html.erb @@ -9,7 +9,7 @@ <% end %> -<%= form_tag({ :action => "save" }) do %> +<%= form_tag account_terms_path, :method => :put do %>

<%= t ".read and accept with tou" %>

diff --git a/app/views/application/_auth_providers.html.erb b/app/views/application/_auth_providers.html.erb index 3feda6139..3edc6edd2 100644 --- a/app/views/application/_auth_providers.html.erb +++ b/app/views/application/_auth_providers.html.erb @@ -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) %>
<%= tag.div :id => "login_auth_buttons", @@ -11,7 +11,7 @@ <% end %>
- <% 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"), diff --git a/app/views/browse/not_found.html.erb b/app/views/browse/not_found.html.erb index 36ee4c883..47b299e03 100644 --- a/app/views/browse/not_found.html.erb +++ b/app/views/browse/not_found.html.erb @@ -2,6 +2,4 @@ <%= render "sidebar_header", :title => t(".title") %> -
-

<%= t ".sorry", :type => t(".type.#{@type}"), :id => params[:id] %> -

+<%= render "not_found_message" %> diff --git a/app/views/changesets/_changeset.html.erb b/app/views/changesets/_changeset.html.erb index 2a3f65859..e29cf01b0 100644 --- a/app/views/changesets/_changeset.html.erb +++ b/app/views/changesets/_changeset.html.erb @@ -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 %>

<%= changeset.tags["comment"].to_s.presence || t("browse.no_comment") %> diff --git a/app/views/changesets/_not_found_message.html.erb b/app/views/changesets/_not_found_message.html.erb new file mode 100644 index 000000000..9297f3b9a --- /dev/null +++ b/app/views/changesets/_not_found_message.html.erb @@ -0,0 +1,3 @@ +

diff --git a/app/views/changesets/show.html.erb b/app/views/changesets/show.html.erb index a47049e99..167bcb5cb 100644 --- a/app/views/changesets/show.html.erb +++ b/app/views/changesets/show.html.erb @@ -6,7 +6,9 @@

<%= linkify(@changeset.tags["comment"].to_s.presence || t("browse.no_comment")) %>

-

<%= changeset_details(@changeset) %>

+ <%= tag.p :class => "details", :data => { :changeset => changeset_data(@changeset) } do %> + <%= changeset_details(@changeset) %> + <% end %> <%= render :partial => "browse/tag_details", :object => @changeset.tags.except("comment") %> diff --git a/app/views/confirmations/confirm.html.erb b/app/views/confirmations/confirm.html.erb index 4f98a8539..08dea27b6 100644 --- a/app/views/confirmations/confirm.html.erb +++ b/app/views/confirmations/confirm.html.erb @@ -28,7 +28,9 @@

- <%= t ".resend_html", - :reconfirm_link => link_to(t(".click_here"), url_for(:action => "confirm_resend")) %> + <%= t ".if_need_resend" %>

+ <%= bootstrap_form_tag :url => url_for(:action => "confirm_resend") do |f| %> + <%= f.submit t(".resend_button"), :class => "btn btn-outline-primary" %> + <% end %> <% end %> diff --git a/app/views/browse/feature.html.erb b/app/views/elements/show.html.erb similarity index 100% rename from app/views/browse/feature.html.erb rename to app/views/elements/show.html.erb diff --git a/app/views/layouts/_header.html.erb b/app/views/layouts/_header.html.erb index 190ea44e5..45e23fc2b 100644 --- a/app/views/layouts/_header.html.erb +++ b/app/views/layouts/_header.html.erb @@ -96,7 +96,7 @@
<% end %> diff --git a/app/views/messages/inbox.html.erb b/app/views/messages/inboxes/show.html.erb similarity index 52% rename from app/views/messages/inbox.html.erb rename to app/views/messages/inboxes/show.html.erb index 835d70a74..4e74dbe1f 100644 --- a/app/views/messages/inbox.html.erb +++ b/app/views/messages/inboxes/show.html.erb @@ -2,12 +2,12 @@ <%= javascript_include_tag "messages" %> <% end %> -<%= render :partial => "heading", :locals => { :active_link_path => inbox_messages_path } %> +<%= render :partial => "heading", :locals => { :active_link_path => messages_inbox_path } %> -

<%= t "messages.inbox.messages", :new_messages => t(".new_messages", :count => current_user.new_messages.size), :old_messages => t(".old_messages", :count => current_user.messages.size - current_user.new_messages.size) %>

+

<%= t ".messages", :new_messages => t(".new_messages", :count => current_user.new_messages.size), :old_messages => t(".old_messages", :count => current_user.messages.size - current_user.new_messages.size) %>

<% if current_user.messages.size > 0 %> - <%= render :partial => "messages_table", :locals => { :columns => %w[from subject date], :messages => current_user.messages, :inner_partial => "message_summary" } %> + <%= render :partial => "messages_table", :locals => { :columns => %w[from subject date], :messages => current_user.messages } %> <% else %>
<%= t(".no_messages_yet_html", :people_mapping_nearby_link => link_to(t(".people_mapping_nearby"), dashboard_path)) %>
<% end %> diff --git a/app/views/messages/_heading.html.erb b/app/views/messages/mailboxes/_heading.html.erb similarity index 60% rename from app/views/messages/_heading.html.erb rename to app/views/messages/mailboxes/_heading.html.erb index c3b479202..ff69f0a38 100644 --- a/app/views/messages/_heading.html.erb +++ b/app/views/messages/mailboxes/_heading.html.erb @@ -3,8 +3,8 @@ <% content_for :heading do %>

<%= t("users.show.my messages") %>