]> git.openstreetmap.org Git - rails.git/commitdiff
Merge remote-tracking branch 'upstream/pull/4823'
authorTom Hughes <tom@compton.nu>
Wed, 22 May 2024 17:37:01 +0000 (18:37 +0100)
committerTom Hughes <tom@compton.nu>
Wed, 22 May 2024 17:37:01 +0000 (18:37 +0100)
48 files changed:
Gemfile
Gemfile.lock
app/assets/javascripts/index/directions.js
app/assets/javascripts/leaflet.layers.js
app/assets/javascripts/leaflet.share.js
app/assets/stylesheets/common.scss
app/controllers/accounts_controller.rb
app/controllers/application_controller.rb
app/controllers/concerns/session_methods.rb
app/controllers/diary_entries_controller.rb
app/controllers/export_controller.rb
app/controllers/messages_controller.rb
app/controllers/oauth2_authorizations_controller.rb
app/controllers/oauth_controller.rb
app/controllers/sessions_controller.rb
app/controllers/site_controller.rb
app/controllers/users_controller.rb
app/helpers/user_helper.rb
app/views/accounts/edit.html.erb
app/views/application/_auth_providers.html.erb
app/views/browse/_node.html.erb
app/views/browse/_relation.html.erb
app/views/browse/_way.html.erb
app/views/changesets/_heading.html.erb
app/views/changesets/show.html.erb
app/views/confirmations/confirm.html.erb
app/views/dashboards/_contact.html.erb
app/views/diary_entries/_diary_comment.html.erb
app/views/diary_entries/_diary_entry.html.erb
app/views/diary_entries/_diary_entry_heading.html.erb
app/views/diary_entries/comments.html.erb
app/views/issues/_comments.html.erb
app/views/issues/_reports.html.erb
app/views/issues/show.html.erb
app/views/layouts/_head.html.erb
app/views/layouts/_header.html.erb
app/views/notes/show.html.erb
app/views/oauth2_applications/_application.html.erb
app/views/oauth2_applications/show.html.erb
app/views/profiles/edit.html.erb
app/views/sessions/new.html.erb
app/views/traces/_trace.html.erb
app/views/users/new.html.erb
app/views/users/show.html.erb
app/views/users/terms.html.erb
config/initializers/content_security_policy.rb
config/initializers/secure_headers.rb [deleted file]
config/initializers/session_store.rb

diff --git a/Gemfile b/Gemfile
index 75387b5d5e3b5c8db060e427ca352e834c6b6014..77a9f1c97ff252c30ce1cd4f66dbd1034c1307ec 100644 (file)
--- a/Gemfile
+++ b/Gemfile
@@ -116,9 +116,6 @@ gem "connection_pool"
 gem "dalli"
 gem "kgio"
 
-# Load secure_headers for Content-Security-Policy support
-gem "secure_headers"
-
 # Load canonical-rails to generate canonical URLs
 gem "canonical-rails"
 
index 23518339bf75b7644df01923eb8af70ed07a9e9a..bf78a3d3d181d2130ec4ee1436b83ad83af866ff 100644 (file)
@@ -529,7 +529,6 @@ GEM
     sass-embedded (1.64.2)
       google-protobuf (~> 3.23)
       rake (>= 13.0.0)
-    secure_headers (6.5.0)
     selenium-webdriver (4.21.1)
       base64 (~> 0.2)
       rexml (~> 3.2, >= 3.2.5)
@@ -690,7 +689,6 @@ DEPENDENCIES
   rubocop-rake
   sanitize
   sass-embedded (~> 1.64.0)
-  secure_headers
   selenium-webdriver
   simplecov
   simplecov-lcov
index 42854f2e2897b8ed19c64c6c6c6c48560dcead3a..89eccb8cbd7d9074fb08d188a7d3875730969a6d 100644 (file)
@@ -307,7 +307,7 @@ OSM.Directions = function (map) {
         var row = $("<tr class='turn'/>");
         row.append("<td class='border-0'><div class='direction i" + direction + "'/></td> ");
         row.append("<td>" + instruction);
-        row.append("<td class='distance text-muted text-end'>" + dist);
+        row.append("<td class='distance text-body-secondary text-end'>" + dist);
 
         row.on("click", function () {
           popup
index 1a34b05c24f80522d6d323e123d31a691c58845c..2702f6017e54d605730181642d668458e9898d17 100644 (file)
@@ -84,7 +84,7 @@ L.OSM.layers = function (options) {
 
       $("<p>")
         .text(I18n.t("javascripts.map.layers.overlays"))
-        .attr("class", "text-muted")
+        .attr("class", "text-body-secondary")
         .appendTo(overlaySection);
 
       var overlays = $("<ul class='list-unstyled form-check'>")
index 69db10ad78ae80069a8c64f8d1c7329942e151f9..0b868d2cac6cf31bdd8688c854a0368559031295 100644 (file)
@@ -98,7 +98,7 @@ L.OSM.share = function (options) {
           .on("click", select))
       .append(
         $("<p>")
-          .attr("class", "text-muted")
+          .attr("class", "text-body-secondary")
           .text(I18n.t("javascripts.share.paste_html")));
 
     // Geo URI
@@ -128,7 +128,7 @@ L.OSM.share = function (options) {
 
     $("<div>")
       .attr("id", "export-warning")
-      .attr("class", "text-muted")
+      .attr("class", "text-body-secondary")
       .text(I18n.t("javascripts.share.only_standard_layer"))
       .appendTo($imageSection);
 
@@ -223,7 +223,7 @@ L.OSM.share = function (options) {
     };
 
     $("<p>")
-      .attr("class", "text-muted")
+      .attr("class", "text-body-secondary")
       .html(I18n.t("javascripts.share.image_dimensions", args))
       .appendTo($form);
 
index b4279016a263d5cec9d3e93abb785feb6ab3d149..0edb3b0fc3cdbb56741946ac3e6da9302f883595 100644 (file)
@@ -50,7 +50,7 @@ time[title] {
 
 /* Utility for de-emphasizing content */
 
-.text-muted a {
+.text-body-secondary a {
   color: $blue;
 }
 
index 6b47ca6660d1ee200691f05b0443178eb1d54997..d45dce66a8e00f6f413831d767436b8b537524e2 100644 (file)
@@ -11,15 +11,13 @@ class AccountsController < ApplicationController
 
   before_action :check_database_readable
   before_action :check_database_writable, :only => [:update]
-  before_action :allow_thirdparty_images, :only => [:edit, :update]
+
+  allow_thirdparty_images :only => [:edit, :update]
+  allow_social_login :only => [:edit, :update]
 
   def edit
     @tokens = current_user.oauth_tokens.authorized
 
-    append_content_security_policy_directives(
-      :form_action => %w[accounts.google.com *.facebook.com login.microsoftonline.com github.com meta.wikimedia.org]
-    )
-
     if errors = session.delete(:user_errors)
       errors.each do |attribute, error|
         current_user.errors.add(attribute, error)
@@ -31,10 +29,6 @@ class AccountsController < ApplicationController
   def update
     @tokens = current_user.oauth_tokens.authorized
 
-    append_content_security_policy_directives(
-      :form_action => %w[accounts.google.com *.facebook.com login.microsoftonline.com github.com meta.wikimedia.org]
-    )
-
     user_params = params.require(:user).permit(:display_name, :new_email, :pass_crypt, :pass_crypt_confirmation, :auth_provider)
 
     if params[:user][:auth_provider].blank? ||
index f5accc3c44d2d65654105a828d5ccc0fc6e94b64..05fa76658d55bedeecf412c4a5d1927cb6ce3899 100644 (file)
@@ -13,13 +13,30 @@ class ApplicationController < ActionController::Base
   rescue_from RailsParam::InvalidParameterError, :with => :invalid_parameter
 
   before_action :fetch_body
-  around_action :better_errors_allow_inline, :if => proc { Rails.env.development? }
 
   attr_accessor :current_user, :oauth_token
 
   helper_method :current_user
   helper_method :oauth_token
 
+  def self.allow_thirdparty_images(**options)
+    content_security_policy(options) do |policy|
+      policy.img_src("*")
+    end
+  end
+
+  def self.allow_social_login(**options)
+    content_security_policy(options) do |policy|
+      policy.form_action(*policy.form_action, "accounts.google.com", "*.facebook.com", "login.microsoftonline.com", "github.com", "meta.wikimedia.org")
+    end
+  end
+
+  def self.allow_all_form_action(**options)
+    content_security_policy(options) do |policy|
+      policy.form_action(nil)
+    end
+  end
+
   private
 
   def authorize_web
@@ -233,13 +250,15 @@ class ApplicationController < ActionController::Base
   end
 
   def map_layout
-    append_content_security_policy_directives(
-      :child_src => %w[http://127.0.0.1:8111 https://127.0.0.1:8112],
-      :frame_src => %w[http://127.0.0.1:8111 https://127.0.0.1:8112],
-      :connect_src => [Settings.nominatim_url, Settings.overpass_url, Settings.fossgis_osrm_url, Settings.graphhopper_url, Settings.fossgis_valhalla_url],
-      :form_action => %w[render.openstreetmap.org],
-      :style_src => %w['unsafe-inline']
-    )
+    policy = request.content_security_policy.clone
+
+    policy.child_src(*policy.child_src, "http://127.0.0.1:8111", "https://127.0.0.1:8112")
+    policy.frame_src(*policy.frame_src, "http://127.0.0.1:8111", "https://127.0.0.1:8112")
+    policy.connect_src(*policy.connect_src, Settings.nominatim_url, Settings.overpass_url, Settings.fossgis_osrm_url, Settings.graphhopper_url, Settings.fossgis_valhalla_url)
+    policy.form_action(*policy.form_action, "render.openstreetmap.org")
+    policy.style_src(*policy.style_src, :unsafe_inline)
+
+    request.content_security_policy = policy
 
     case Settings.status
     when "database_offline", "api_offline"
@@ -251,10 +270,6 @@ class ApplicationController < ActionController::Base
     request.xhr? ? "xhr" : "map"
   end
 
-  def allow_thirdparty_images
-    append_content_security_policy_directives(:img_src => %w[*])
-  end
-
   def preferred_editor
     if params[:editor]
       params[:editor]
@@ -277,17 +292,6 @@ class ApplicationController < ActionController::Base
     end
   end
 
-  def better_errors_allow_inline
-    yield
-  rescue StandardError
-    append_content_security_policy_directives(
-      :script_src => %w['unsafe-inline'],
-      :style_src => %w['unsafe-inline']
-    )
-
-    raise
-  end
-
   def current_ability
     Ability.new(current_user)
   end
index 5dcddb82debb5e4849039c28e2d4cf128d6f5c5f..45cf0d9439607642725c088feb5517215e232524 100644 (file)
@@ -39,7 +39,7 @@ module SessionMethods
     session[:fingerprint] = user.fingerprint
     session_expires_after 28.days if session[:remember_me]
 
-    target = referer || session[:referer] || url_for(:controller => :site, :action => :index)
+    target = referer || url_for(:controller => :site, :action => :index)
 
     # The user is logged in, so decide where to send them:
     #
@@ -56,31 +56,28 @@ module SessionMethods
     end
 
     session.delete(:remember_me)
-    session.delete(:referer)
   end
 
   ##
   # process a failed login
-  def failed_login(message, username = nil)
+  def failed_login(message, username, referer = nil)
     flash[:error] = message
 
-    redirect_to :controller => "sessions", :action => "new", :referer => session[:referer],
+    redirect_to :controller => "sessions", :action => "new", :referer => referer,
                 :username => username, :remember_me => session[:remember_me]
 
     session.delete(:remember_me)
-    session.delete(:referer)
   end
 
   ##
   #
-  def unconfirmed_login(user)
+  def unconfirmed_login(user, referer = nil)
     session[:pending_user] = user.id
 
     redirect_to :controller => "confirmations", :action => "confirm",
-                :display_name => user.display_name, :referer => session[:referer]
+                :display_name => user.display_name, :referer => referer
 
     session.delete(:remember_me)
-    session.delete(:referer)
   end
 
   ##
index 8da0842eb09cbee7942cf28d725d5ee6b49e9308..9af36709eb20be1a2055a964daf2697d3443af1f 100644 (file)
@@ -12,7 +12,8 @@ class DiaryEntriesController < ApplicationController
 
   before_action :lookup_user, :only => [:show, :comments]
   before_action :check_database_writable, :only => [:new, :create, :edit, :update, :comment, :hide, :hidecomment, :subscribe, :unsubscribe]
-  before_action :allow_thirdparty_images, :only => [:new, :create, :edit, :update, :index, :show, :comments]
+
+  allow_thirdparty_images :only => [:new, :create, :edit, :update, :index, :show, :comments]
 
   def index
     if params[:display_name]
index 94851de96485741758d681a1247be029c402dc17..cddc97b6883e13044601c5b4a3a24b1f84d83f74 100644 (file)
@@ -4,6 +4,10 @@ class ExportController < ApplicationController
   before_action :update_totp, :only => [:finish]
   authorize_resource :class => false
 
+  content_security_policy(:only => :embed) do |policy|
+    policy.frame_ancestors("*")
+  end
+
   caches_page :embed
 
   # When the user clicks 'Export' we redirect to a URL which generates the export download
@@ -25,9 +29,5 @@ class ExportController < ApplicationController
     end
   end
 
-  def embed
-    append_content_security_policy_directives(
-      :frame_ancestors => %w[*]
-    )
-  end
+  def embed; end
 end
index adfbd9157992537c18c35b35beb1c67513dbef03..779174e255ffc915fe14f44c67e2710b8cb87cba 100644 (file)
@@ -11,7 +11,8 @@ 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 :allow_thirdparty_images, :only => [:new, :create, :show]
+
+  allow_thirdparty_images :only => [:new, :create, :show]
 
   # Show a message
   def show
index dca95de4e7a34b737906ba2dd524d1c7b2e3f49f..415ab2775c12f248e90598bde7e2495078e126f9 100644 (file)
@@ -3,13 +3,8 @@ class Oauth2AuthorizationsController < Doorkeeper::AuthorizationsController
 
   prepend_before_action :authorize_web
   before_action :set_locale
-  before_action :allow_all_form_action, :only => [:new]
 
-  authorize_resource :class => false
-
-  private
+  allow_all_form_action :only => :new
 
-  def allow_all_form_action
-    override_content_security_policy_directives(:form_action => []) if Settings.csp_enforce || Settings.key?(:csp_report_url)
-  end
+  authorize_resource :class => false
 end
index 49af05b0d188e814960468d0a0f335cfd989f62e..62a68b53369ddc0e2cf4829a9a4c40f4d5f552d5 100644 (file)
@@ -9,6 +9,8 @@ class OauthController < ApplicationController
 
   layout "site"
 
+  allow_all_form_action :only => :oauth1_authorize
+
   def revoke
     @token = current_user.oauth_tokens.find_by :token => params[:token]
     if @token
@@ -41,8 +43,6 @@ class OauthController < ApplicationController
   end
 
   def oauth1_authorize
-    override_content_security_policy_directives(:form_action => []) if Settings.csp_enforce || Settings.key?(:csp_report_url)
-
     if @token.invalidated?
       @message = t "oauth.authorize_failure.invalid"
       render :action => "authorize_failure"
index fdf2df6a753cf51f1e639495ebe5d9b3c3477ba1..a3e6f42f03db4b172607bc26285d6c79c3b0ee8b 100644 (file)
@@ -11,18 +11,20 @@ class SessionsController < ApplicationController
 
   authorize_resource :class => false
 
-  def new
-    override_content_security_policy_directives(:form_action => []) if Settings.csp_enforce || Settings.key?(:csp_report_url)
+  allow_all_form_action :only => :new
 
-    session[:referer] = safe_referer(params[:referer]) if params[:referer]
+  def new
+    referer = safe_referer(params[:referer]) if params[:referer]
 
-    parse_oauth_referer session[:referer]
+    parse_oauth_referer referer
   end
 
   def create
     session[:remember_me] ||= params[:remember_me]
-    session[:referer] = safe_referer(params[:referer]) if params[:referer]
-    password_authentication(params[:username].strip, params[:password])
+
+    referer = safe_referer(params[:referer]) if params[:referer]
+
+    password_authentication(params[:username].strip, params[:password], referer)
   end
 
   def destroy
@@ -43,15 +45,15 @@ class SessionsController < ApplicationController
 
   ##
   # handle password authentication
-  def password_authentication(username, password)
+  def password_authentication(username, password, referer = nil)
     if (user = User.authenticate(:username => username, :password => password))
-      successful_login(user)
+      successful_login(user, referer)
     elsif (user = User.authenticate(:username => username, :password => password, :pending => true))
-      unconfirmed_login(user)
+      unconfirmed_login(user, referer)
     elsif User.authenticate(:username => username, :password => password, :suspended => true)
-      failed_login({ :partial => "sessions/suspended_flash" }, username)
+      failed_login({ :partial => "sessions/suspended_flash" }, username, referer)
     else
-      failed_login t("sessions.new.auth failure"), username
+      failed_login(t("sessions.new.auth failure"), username, referer)
     end
   end
 end
index 3d830c63f7fab352aa47b893a7c3fdfa0d9a9e07..172be56531df7e444e4c7ed3b94236480378c660 100644 (file)
@@ -12,6 +12,17 @@ class SiteController < ApplicationController
 
   authorize_resource :class => false
 
+  content_security_policy(:only => :edit) do |policy|
+    policy.frame_src(*policy.frame_src, :blob)
+  end
+
+  content_security_policy(:only => :id) do |policy|
+    policy.connect_src("*")
+    policy.img_src("*", :blob)
+    policy.script_src(*policy.script_src, "dev.virtualearth.net", :unsafe_eval)
+    policy.style_src(*policy.style_src, :unsafe_inline)
+  end
+
   def index
     session[:location] ||= OSM.ip_location(request.env["REMOTE_ADDR"]) unless Settings.status == "database_readonly" || Settings.status == "database_offline"
   end
@@ -71,12 +82,6 @@ class SiteController < ApplicationController
       require_user
     end
 
-    if %w[id].include?(editor)
-      append_content_security_policy_directives(
-        :frame_src => %w[blob:]
-      )
-    end
-
     begin
       if params[:node]
         bbox = Node.visible.find(params[:node]).bbox.to_unscaled
@@ -136,13 +141,6 @@ class SiteController < ApplicationController
   end
 
   def id
-    append_content_security_policy_directives(
-      :connect_src => %w[*],
-      :img_src => %w[* blob:],
-      :script_src => %w[dev.virtualearth.net 'unsafe-eval'],
-      :style_src => %w['unsafe-inline']
-    )
-
     render :layout => false
   end
 
index 2cdec642d33ed8a4876defd7f53100b97b1d18f6..186e06120e0f70de52db61d112ec88c82240b9c5 100644 (file)
@@ -17,7 +17,9 @@ class UsersController < ApplicationController
   before_action :check_database_writable, :only => [:new, :go_public]
   before_action :require_cookies, :only => [:new]
   before_action :lookup_user_by_name, :only => [:set_status, :destroy]
-  before_action :allow_thirdparty_images, :only => [:show]
+
+  allow_thirdparty_images :only => :show
+  allow_social_login :only => :new
 
   ##
   # display a list of users matching specified criteria
@@ -54,18 +56,10 @@ class UsersController < ApplicationController
 
   def new
     @title = t ".title"
-    @referer = if params[:referer]
-                 safe_referer(params[:referer])
-               else
-                 session[:referer]
-               end
+    @referer = safe_referer(params[:referer])
 
     parse_oauth_referer @referer
 
-    append_content_security_policy_directives(
-      :form_action => %w[accounts.google.com *.facebook.com login.microsoftonline.com github.com meta.wikimedia.org]
-    )
-
     if current_user
       # The user is logged in already, so don't show them the signup
       # page, instead send them to the home page
@@ -94,10 +88,6 @@ class UsersController < ApplicationController
     self.current_user = User.new(user_params)
 
     if check_signup_allowed(current_user.email)
-      session[:referer] = safe_referer(params[:referer]) if params[:referer]
-
-      Rails.logger.info "create: #{session[:referer]}"
-
       if current_user.auth_uid.present?
         # We are creating an account with external authentication and
         # no password was specified so create a random one
@@ -115,7 +105,7 @@ class UsersController < ApplicationController
       else
         # Save the user record
         session[:new_user] = current_user.slice("email", "display_name", "pass_crypt", "pass_crypt_confirmation")
-        save_new_user params[:email_hmac]
+        save_new_user params[:email_hmac], params[:referer]
       end
     end
   end
@@ -200,6 +190,7 @@ class UsersController < ApplicationController
   ##
   # omniauth success callback
   def auth_success
+    referer = request.env["omniauth.params"]["referer"]
     auth_info = request.env["omniauth.auth"]
 
     provider = auth_info[:provider]
@@ -233,7 +224,7 @@ class UsersController < ApplicationController
       session[:new_user]["auth_uid"] = uid
 
       email_hmac = UsersController.message_hmac(email) if email_verified && email
-      save_new_user email_hmac
+      save_new_user email_hmac, referer
     else
       user = User.find_by(:auth_provider => provider, :auth_uid => uid)
 
@@ -246,13 +237,13 @@ class UsersController < ApplicationController
       if user
         case user.status
         when "pending"
-          unconfirmed_login(user)
+          unconfirmed_login(user, referer)
         when "active", "confirmed"
-          successful_login(user, request.env["omniauth.params"]["referer"])
+          successful_login(user, referer)
         when "suspended"
-          failed_login({ :partial => "sessions/suspended_flash" })
+          failed_login({ :partial => "sessions/suspended_flash" }, user.display_name, referer)
         else
-          failed_login t("sessions.new.auth failure")
+          failed_login(t("sessions.new.auth failure"), user.display_name, referer)
         end
       else
         email_hmac = UsersController.message_hmac(email) if email_verified && email
@@ -281,7 +272,7 @@ class UsersController < ApplicationController
 
   private
 
-  def save_new_user(email_hmac)
+  def save_new_user(email_hmac, referer = nil)
     new_user = session.delete(:new_user)
     self.current_user = User.new(new_user)
     if check_signup_allowed(current_user.email)
@@ -306,11 +297,10 @@ class UsersController < ApplicationController
 
         flash[:matomo_goal] = Settings.matomo["goals"]["signup"] if defined?(Settings.matomo)
 
-        referer = welcome_path(welcome_options)
+        referer = welcome_path(welcome_options(referer))
 
         if current_user.status == "active"
-          session[:referer] = referer
-          successful_login(current_user)
+          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
@@ -322,8 +312,8 @@ class UsersController < ApplicationController
     end
   end
 
-  def welcome_options
-    uri = URI(session[:referer]) if session[:referer].present?
+  def welcome_options(referer = nil)
+    uri = URI(referer) if referer.present?
 
     return { "oauth_return_url" => uri&.to_s } if uri&.path == oauth_authorization_path
 
index 20e8a2292dcc4b24450b4391cce0c0199fc0b2fd..e2de9934f6a5131150debf676c89265902b13676 100644 (file)
@@ -77,7 +77,7 @@ module UserHelper
                 :size => "24") + t("application.auth_providers.#{name}.title"),
       auth_path(options.merge(:provider => provider)),
       :method => :post,
-      :class => "auth_button fs-6 border rounded text-muted text-decoration-none py-2 px-4 d-flex justify-content-center align-items-center",
+      :class => "auth_button fs-6 border rounded text-body-secondary text-decoration-none py-2 px-4 d-flex justify-content-center align-items-center",
       :title => t("application.auth_providers.#{name}.title")
     )
   end
index e783367dd1b9600812e670e12c752aef3cba5a59..dc649cbf491fb9a2925f1fd0303a26ff0234b8fa 100644 (file)
       <%= f.select(:auth_provider, Auth.providers, :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-muted">(<a href="<%= t ".openid.link" %>" target="_new"><%= t ".openid.link text" %></a>)</small>
+    <small class="form-text text-body-secondary">(<a href="<%= t ".openid.link" %>" target="_new"><%= t ".openid.link text" %></a>)</small>
   </fieldset>
 
   <div class="mb-3">
     <label class="form-label"><%= t ".public editing.heading" %></label>
-    <span class="form-text text-muted">
+    <span class="form-text text-body-secondary">
       <% if current_user.data_public? %>
         <%= t ".public editing.enabled" %>
         (<a href="<%= t ".public editing.enabled link" %>" target="_new"><%= t ".public editing.enabled link text" %></a>)
@@ -40,7 +40,7 @@
 
   <div class="mb-3">
     <label class="form-label"><%= t ".contributor terms.heading" %></label>
-    <span class="form-text text-muted">
+    <span class="form-text text-body-secondary">
       <% if current_user.terms_agreed? %>
         <%= t ".contributor terms.agreed" %>
         (<a href="<%= t ".contributor terms.link" %>" target="_new"><%= t ".contributor terms.link text" %></a>)
index a79e7b5ce3cf75e920d1e91d11664b590cf50a21..554ec8ddaa30c235b02e7efb603506c96518b636 100644 (file)
@@ -36,7 +36,7 @@
       <label for="openid_url" class="form-label"><%= t ".openid_html", :logo => openid_logo %></label>
       <%= hidden_field_tag("referer", params[:referer], :autocomplete => "off") %>
       <%= text_field_tag("openid_url", "", :tabindex => 20, :autocomplete => "on", :class => "openid_url form-control") %>
-      <span class="form-text text-muted">(<a href="<%= t "accounts.edit.openid.link" %>" target="_new"><%= t "accounts.edit.openid.link text" %></a>)</span>
+      <span class="form-text text-body-secondary">(<a href="<%= t "accounts.edit.openid.link" %>" target="_new"><%= t "accounts.edit.openid.link text" %></a>)</span>
     </div>
 
     <%= submit_tag t(".openid_login_button"), :tabindex => 21, :id => "openid_login_button", :class => "btn btn-primary" %>
index 4e2ae0343d2e57f5ba7a460b5701892ed0d923b3..0ffe7c68b82dd01c9cbafe2ca6966295d4b8532a 100644 (file)
@@ -7,7 +7,7 @@
                                        :id => node.redaction.id), node.redaction) %>
   </div>
 <% else %>
-  <%= tag.div :class => ["browse-section", "browse-node", { "text-muted" => node.redacted? }] do %>
+  <%= tag.div :class => ["browse-section", "browse-node", { "text-body-secondary" => node.redacted? }] do %>
     <%= render :partial => "browse/common_details", :object => node %>
 
     <% unless node.ways.empty? and node.containing_relation_members.empty? %>
index a987fe4d8e179bdedd701197e80e1a8c22a45302..5dcdffa47f6cc683d657fa8ad215adf546234c7f 100644 (file)
@@ -7,7 +7,7 @@
                                        :id => relation.redaction.id), relation.redaction) %>
   </div>
 <% else %>
-  <%= tag.div :class => ["browse-section", "browse-relation", { "text-muted" => relation.redacted? }] do %>
+  <%= tag.div :class => ["browse-section", "browse-relation", { "text-body-secondary" => relation.redacted? }] do %>
     <%= render :partial => "browse/common_details", :object => relation %>
 
     <% unless relation.containing_relation_members.empty? %>
index d015438fe998568ae45c1a454ff63f8e6ef0b2d7..d04eff14030183432704277a9e07802b378c2083 100644 (file)
@@ -7,7 +7,7 @@
                                        :id => way.redaction.id), way.redaction) %>
   </div>
 <% else %>
-  <%= tag.div :class => ["browse-section", "browse-way", { "text-muted" => way.redacted? }] do %>
+  <%= tag.div :class => ["browse-section", "browse-way", { "text-body-secondary" => way.redacted? }] do %>
     <%= render :partial => "browse/common_details", :object => way %>
 
     <% unless way.containing_relation_members.empty? %>
index a125a135a5ff34c315f47cde4e4f0781492ee771..acb6c9834a20fb72adace17eb8c6144db7e892c1 100644 (file)
@@ -9,7 +9,7 @@
     </div>
   </div>
 
-  <small class='text-muted'>
+  <small class='text-body-secondary'>
     <%= t(".created_by_html", :link_user => link_to(changeset.user.display_name, changeset.user), :created => l(changeset.created_at, :format => :blog)) %>
   </small>
 </div>
index 3ba3968f704b20626496e189676fec7e9e831994..d44ccfc075934a552ea4fc5c0ccf557de937ec15 100644 (file)
@@ -31,7 +31,7 @@
       <% @comments.each do |comment| %>
         <% next unless comment.visible || current_user&.moderator? %>
         <li id="c<%= comment.id %>">
-          <small class='text-muted'>
+          <small class='text-body-secondary'>
             <%= t comment.visible ? ".comment_by_html" : ".hidden_comment_by_html",
                   :time_ago => friendly_date_ago(comment.created_at),
                   :user => link_to(comment.author.display_name, comment.author) %>
index 879fb8f337cebf45c1a4f15ff46efdd1d5c422a6..4f98a85399a206d93f0be0dca30d3a9d49676e40 100644 (file)
 <% else %>
   <h1>
     <%= t ".introduction_1" %>
-    <span class="text-muted">
+    <span class="text-body-secondary">
       <%= t ".introduction_2" %>
     </span>
   </h1>
 
-  <p class='text-muted'>
+  <p class='text-body-secondary'>
     <%= t ".resend_html",
           :reconfirm_link => link_to(t(".click_here"), url_for(:action => "confirm_resend")) %>
   </p>
index b28a28a26770ead4a7ffd029bcab072d8bf63a5e..759faab8f7d50d713a301ffab32b29d6ba959e65 100644 (file)
@@ -9,7 +9,7 @@
     <%= user_thumbnail contact %>
   </div>
   <div class="col">
-    <p class='text-muted mb-0'>
+    <p class='text-body-secondary mb-0'>
       <%= link_to contact.display_name, contact %>
       <% if @user.home_location? and contact.home_location? %>
         <% distance = @user.distance(contact) %>
@@ -32,7 +32,7 @@
     </p>
 
     <nav class='secondary-actions'>
-      <ul class='clearfix text-muted'>
+      <ul class='clearfix text-body-secondary'>
         <li><%= link_to t("users.show.send message"), new_message_path(contact) %></li>
         <li>
           <% if current_user.friends_with?(contact) %>
index 5ade361aa1ac66ff90f0f70f1981a0e94a5f4637..c3c68fbc9934f0afdf2592e876f680d1ff9220f3 100644 (file)
@@ -1,9 +1,9 @@
-<div class="row diary-comment border-bottom py-3<%= " text-muted bg-danger bg-opacity-10" unless diary_comment.visible? %>">
+<div class="row diary-comment border-bottom py-3<%= " text-body-secondary bg-danger bg-opacity-10" unless diary_comment.visible? %>">
   <div class="col-auto pe-0 text-center">
     <%= user_thumbnail diary_comment.user %>
   </div>
   <div class="col">
-    <p class="text-muted m-0" id="comment<%= diary_comment.id %>"><%= t(".comment_from_html", :link_user => (link_to diary_comment.user.display_name, diary_comment.user), :comment_created_at => link_to(l(diary_comment.created_at, :format => :friendly), :anchor => "comment#{diary_comment.id}")) %>
+    <p class="text-body-secondary m-0" id="comment<%= diary_comment.id %>"><%= t(".comment_from_html", :link_user => (link_to diary_comment.user.display_name, diary_comment.user), :comment_created_at => link_to(l(diary_comment.created_at, :format => :friendly), :anchor => "comment#{diary_comment.id}")) %>
       <% if current_user and diary_comment.user.id != current_user.id %>
         | <%= report_link(t(".report"), diary_comment) %>
       <% end %>
index 9c7d7b2dc297bc211c6772d3902048eb60f9e0f0..d4ee530d7f9d80b7787ccdf52b20fd37b261a2cd 100644 (file)
@@ -1,4 +1,4 @@
-<article class='diary_post border-top border-secondary-subtle py-3<%= " text-muted px-3 bg-danger bg-opacity-10" unless diary_entry.visible %> user_<%= diary_entry.user.id %>'>
+<article class='diary_post border-top border-secondary-subtle py-3<%= " text-body-secondary px-3 bg-danger bg-opacity-10" unless diary_entry.visible %> user_<%= diary_entry.user.id %>'>
   <%= render :partial => "diary_entry_heading", :object => diary_entry, :as => "diary_entry" %>
 
   <div class="richtext text-break" xml:lang="<%= diary_entry.language_code %>" lang="<%= diary_entry.language_code %>">
index 30f7bc03baf2a13a27e4827901a1d1849dffc35d..b6dca2ee41da292f471562040cbe4c1ac45d54bc 100644 (file)
@@ -12,7 +12,7 @@
     </div>
   <% end %>
 
-  <small class='text-muted'>
+  <small class='text-body-secondary'>
     <%= t("diary_entries.diary_entry.posted_by_html", :link_user => (link_to diary_entry.user.display_name, diary_entry.user), :created => l(diary_entry.created_at, :format => :blog), :language_link => (link_to diary_entry.language.name, :controller => "diary_entries", :action => "index", :display_name => nil, :language => diary_entry.language_code)) %>
     <% if (l(diary_entry.updated_at, :format => :blog) != l(diary_entry.created_at, :format => :blog)) %>
       <%= t("diary_entries.diary_entry.updated_at_html", :updated => l(diary_entry.updated_at, :format => :blog)) %>
index aa0fceb95c921046bb962547c7a5816f8089692b..aa5c163847912083e64b706c9112910f869657a3 100644 (file)
     </thead>
     <% @comments.each do |comment| -%>
     <tr>
-      <td width="25%" class="<%= "text-muted" unless comment.visible? %>"><%= link_to comment.diary_entry.title, diary_entry_path(comment.diary_entry.user, comment.diary_entry) %></td>
-      <td width="25%" class="<%= "text-muted" unless comment.visible? %>">
+      <td width="25%" class="<%= "text-body-secondary" unless comment.visible? %>"><%= link_to comment.diary_entry.title, diary_entry_path(comment.diary_entry.user, comment.diary_entry) %></td>
+      <td width="25%" class="<%= "text-body-secondary" unless comment.visible? %>">
         <%= friendly_date_ago(comment.created_at) %>
       </td>
-      <td width="50%" class="richtext text-break<%= " text-muted" unless comment.visible? %>"><%= comment.body.to_html %></td>
+      <td width="50%" class="richtext text-break<%= " text-body-secondary" unless comment.visible? %>"><%= comment.body.to_html %></td>
     </tr>
     <% end -%>
   </table>
index 9200b4cec6246b8feebcc7dbaab1eee77fe19a43..f828e5a4350b4a80bb64306190aa85ecc4cd18bd 100644 (file)
@@ -5,7 +5,7 @@
         <%= link_to user_thumbnail(comment.user), comment.user %>
       </div>
       <div class="col">
-        <p class="text-muted">
+        <p class="text-body-secondary">
           <%= t ".comment_from_html", :user_link => link_to(comment.user.display_name, comment.user),
                                       :comment_created_at => tag.time(l(comment.created_at.to_datetime, :format => :friendly),
                                                                       :datetime => comment.created_at.xmlschema) %>
index 2d1b78800688bcb17d024b1d603c83fed890dd36..2d0f1650bdf4f3c2040c0c8c09086f7641ef7f92 100644 (file)
@@ -4,7 +4,7 @@
       <%= link_to user_thumbnail(report.user), report.user %>
     </div>
     <div class="col">
-      <p class="text-muted">
+      <p class="text-body-secondary">
         <%= t ".reported_by_html", :category => report.category,
                                    :user => link_to(report.user.display_name, report.user),
                                    :updated_at => tag.time(l(report.updated_at.to_datetime, :format => :friendly),
index ad463c259320daa443ac57d4836a2faf30d4059a..a58b8c5cb18b4f36c4bb1c0bf978618dc08b0255 100644 (file)
@@ -1,7 +1,7 @@
 <% content_for :heading do %>
 <h1><%= t ".title", :status => @issue.status.humanize, :issue_id => @issue.id %></h1>
 <p><%= @issue.reportable.model_name.human %> : <%= link_to reportable_title(@issue.reportable), reportable_url(@issue.reportable) %></p>
-<p class="text-muted">
+<p class="text-body-secondary">
   <small>
     <%= @issue.assigned_role %>
     <% if @issue.reports.count > 0 %>
@@ -45,7 +45,7 @@
     <h3><%= t ".reports_of_this_issue" %></h3>
 
     <% if @read_reports.present? %>
-    <div class="bg-body-tertiary text-muted">
+    <div class="bg-body-tertiary text-body-secondary">
       <h4><%= t ".read_reports" %></h4>
       <%= render "reports", :reports => @read_reports %>
     </div>
index 724ca552635e4582313d043070a85b3077a5faa7..3c691612ab1d4c37ec1ad7a0f8c001b334e50272 100644 (file)
@@ -12,6 +12,6 @@
   <%= yield :head %>
   <%= yield :auto_discovery_link_tag %>
   <%= csrf_meta_tag %>
-  <meta name="csp-nonce" content="<%= content_security_policy_style_nonce %>" />
+  <%= csp_meta_tag %>
   <title><%= "#{@title} | " if @title %><%= t "layouts.project_name.title" %></title>
 <% end %>
index aa05aff843206403bf80fad55e35e119fe3dbba6..8516efc49e51ed9e01f045db900f6d782f727044 100644 (file)
           <% if current_user.new_messages.size > 0 %>
             <span class="badge count-number m-1"><%= current_user.new_messages.size %></span>
           <% end %>
-          <span class="user-button">
-            <span class='username'>
-              <%= current_user.display_name %>
-            </span>
+          <span class='username'>
+            <%= current_user.display_name %>
           </span>
         </button>
         <div class='dropdown-menu dropdown-menu-end'>
index a7baccf856dec921056d6c40fd8da7a8c75ff685..79cc46b09353e9b304a80c6c6b4c1aef36d4ca30 100644 (file)
@@ -33,7 +33,7 @@
       <ul class="list-unstyled">
         <% @note_comments.drop(1).each do |comment| %>
           <li id="c<%= comment.id %>">
-            <small class='text-muted'><%= note_event(comment.event, comment.created_at, comment.author) %></small>
+            <small class='text-body-secondary'><%= note_event(comment.event, comment.created_at, comment.author) %></small>
             <div class="mx-2">
               <%= comment.body.to_html %>
             </div>
@@ -90,7 +90,7 @@
 
   <% if current_user && current_user != @note.author %>
     <p>
-      <small class="text-muted">
+      <small class="text-body-secondary">
         <%= t ".report_link_html", :link => report_link(t(".report"), @note) %>
         <% if @note.status == "open" %>
           <%= t ".other_problems_resolve", :link => report_link(t(".report"), @note) %>
   <% end %>
 
   <% if @note.freshly_closed? %>
-    <small class="text-muted">
+    <small class="text-body-secondary">
       <%= t ".disappear_date_html", :disappear_in => friendly_date(@note.freshly_closed_until) %>
     </small>
   <% end %>
index 57e852182941301acd09cb75543270dc149a406b..796e3e776857c551d06349c413d95333184d06cf 100644 (file)
@@ -3,14 +3,14 @@
     <ul class="list-unstyled mb-0">
       <li><%= link_to application.name, oauth_application_path(application) %></li>
       <% application.redirect_uri.split.each do |uri| -%>
-        <li class="text-muted"><%= uri %></li>
+        <li class="text-body-secondary"><%= uri %></li>
       <% end -%>
     </ul>
   </td>
   <td class="align-middle">
     <ul class="list-unstyled mb-0">
       <% application.scopes.each do |scope| -%>
-        <li><%= authorization_scope(scope) %> <code class="text-muted">(<%= scope %>)</code></li>
+        <li><%= authorization_scope(scope) %> <code class="text-body-secondary">(<%= scope %>)</code></li>
       <% end -%>
     </ul>
   </td>
index 8d9c8516dfd297ad5494e946a082d464bd16631b..2c4557c1e301ad4c4a9c90176de26816570d1787 100644 (file)
@@ -28,7 +28,7 @@
     <td>
       <ul class="list-unstyled mb-0">
         <% @application.scopes.each do |scope| -%>
-          <li><%= t "oauth.scopes.#{scope}" %> <code class="text-muted">(<%= scope %>)</code></li>
+          <li><%= t "oauth.scopes.#{scope}" %> <code class="text-body-secondary">(<%= scope %>)</code></li>
         <% end -%>
       </ul>
     </td>
index d755be52cae4b7d3f0bb931f9de4351f6d13db8a..fea15eb2fa4913628e0f23d57bf14f945e36ea32 100644 (file)
@@ -42,7 +42,7 @@
 
   <fieldset>
     <legend><%= t ".home location" -%></legend>
-    <p id="home_message" class="text-muted m-0<% if current_user.home_location? %> invisible<% end %>"><%= t ".no home location" %></p>
+    <p id="home_message" class="text-body-secondary m-0<% if current_user.home_location? %> invisible<% end %>"><%= t ".no home location" %></p>
     <div class="row">
       <%= f.text_field :home_lat, :wrapper_class => "col-sm-4 d-flex flex-column", :class => "mt-auto", :id => "home_lat" %>
       <%= f.text_field :home_lon, :wrapper_class => "col-sm-4 d-flex flex-column", :class => "mt-auto", :id => "home_lon" %>
index 71c0a14f3d2d2c7c58600eb9bcf170f8b5de2704..89d747ebc90de11fbdb6ced6e754b09d9243a193 100644 (file)
@@ -7,7 +7,7 @@
 
 <% content_for :heading do %>
   <% if @client_app_name %>
-    <p class="text-center text-muted fs-6 py-2 mb-0 bg-body"><%= t(".login_to_authorize_html", :client_app_name => @client_app_name) %></p>
+    <p class="text-center text-body-secondary fs-6 py-2 mb-0 bg-body"><%= t(".login_to_authorize_html", :client_app_name => @client_app_name) %></p>
   <% end %>
 
   <div class="header-illustration new-user-main auth-container mx-auto">
@@ -16,7 +16,7 @@
         <%= link_to t("sessions.new.tab_title"), "#", :class => "nav-link active" %>
       </li>
       <li class="nav-item">
-        <%= link_to t("users.new.tab_title"), url_for(:action => :new, :controller => :users), :class => "nav-link" %>
+        <%= link_to t("users.new.tab_title"), url_for(:action => :new, :controller => :users, :referer => params[:referer]), :class => "nav-link" %>
       </li>
     </ul>
   </div>
@@ -35,7 +35,7 @@
   <%= bootstrap_form_tag(:action => "login", :html => { :id => "login_form" }) do |f| %>
     <%= hidden_field_tag("referer", h(params[:referer]), :autocomplete => "off") %>
 
-    <%= f.text_field :username, :label => t(".email or username"), :tabindex => 1, :value => params[:username] %>
+    <%= f.text_field :username, :label => t(".email or username"), :autofocus => true, :tabindex => 1, :value => params[:username] %>
 
     <div class="row">
       <div class="col">
index cd4dce99e1c2eca1592f1213027ec22a1f3c7fa6..37713679f1c12ee6a58ee7119f1f8999de900f3f 100644 (file)
@@ -30,7 +30,7 @@
         <span class="badge bg-<%= badge_class %> text-white"><%= t(".#{trace.visibility}") %></span>
       </li>
     </ul>
-    <p class="text-muted mb-0">
+    <p class="text-body-secondary mb-0">
       <% if trace.tags.empty? %>
         <%= t ".details_without_tags_html", :time_ago => friendly_date_ago(trace.timestamp),
                                             :user => link_to(trace.user.display_name, trace.user) %>
index a2a06836066398b467da603578321a1c93a1ba09..ae4483757b8262a514be778bb1483d1ede826f30 100644 (file)
@@ -7,13 +7,13 @@
 
 <% content_for :heading do %>
   <% if @client_app_name %>
-    <p class="text-center text-muted fs-6 py-2 mb-0 bg-body"><%= t(".signup_to_authorize_html", :client_app_name => @client_app_name) %></p>
+    <p class="text-center text-body-secondary fs-6 py-2 mb-0 bg-body"><%= t(".signup_to_authorize_html", :client_app_name => @client_app_name) %></p>
   <% end %>
 
   <div class="header-illustration new-user-main auth-container mx-auto">
     <ul class="nav nav-tabs position-absolute bottom-0 px-3 fs-6 w-100">
       <li class="nav-item">
-        <%= link_to t("sessions.new.tab_title"), url_for(:action => :new, :controller => :sessions), :class => "nav-link" %>
+        <%= link_to t("sessions.new.tab_title"), url_for(:action => :new, :controller => :sessions, :referer => @referer), :class => "nav-link" %>
       </li>
       <li class="nav-item">
         <%= link_to t("users.new.tab_title"), "#", :class => "nav-link active" %>
@@ -24,7 +24,7 @@
 
 <div class="auth-container mx-auto my-0">
   <% if current_user.auth_uid.nil? %>
-    <div class="text-muted fs-6">
+    <div class="text-body-secondary fs-6">
       <p><strong><%= t ".about.header" %></strong> <%= t ".about.paragraph_1" %></p>
       <p><%= t ".about.paragraph_2" %></p>
     </div>
@@ -53,6 +53,7 @@
                                                                            t(".privacy_policy_url"),
                                                                            :title => t(".privacy_policy_title"),
                                                                            :target => :new)),
+                                :autofocus => true,
                                 :tabindex => 1 %>
     <% else %>
       <%= f.hidden_field :email %>
       </div>
     <% end %>
 
-    <p class="mb-3 text-muted fs-6"><%= t(".by_signing_up_html",
-                                          :tou_link => link_to(t("layouts.tou"),
-                                                               "https://wiki.osmfoundation.org/wiki/Terms_of_Use",
-                                                               :target => :new),
-                                          :privacy_policy_link => link_to(t(".privacy_policy"),
-                                                                          t(".privacy_policy_url"),
-                                                                          :title => t(".privacy_policy_title"),
-                                                                          :target => :new),
-                                          :contributor_terms_link => link_to(t(".contributor_terms"),
-                                                                             t(".contributor_terms_url"),
-                                                                             :target => :new)) %></p>
+    <p class="mb-3 text-body-secondary fs-6"><%= t(".by_signing_up_html",
+                                                   :tou_link => link_to(t("layouts.tou"),
+                                                                        "https://wiki.osmfoundation.org/wiki/Terms_of_Use",
+                                                                        :target => :new),
+                                                   :privacy_policy_link => link_to(t(".privacy_policy"),
+                                                                                   t(".privacy_policy_url"),
+                                                                                   :title => t(".privacy_policy_title"),
+                                                                                   :target => :new),
+                                                   :contributor_terms_link => link_to(t(".contributor_terms"),
+                                                                                      t(".contributor_terms_url"),
+                                                                                      :target => :new)) %></p>
     <%= f.form_group do %>
       <%= f.check_box :consider_pd,
                       :tabindex => 5,
index 9da3f8f046884b37279fb2a579852006b277e41a..b6c5c6053373fa380045b51dc01564b18a68ace8 100644 (file)
         </nav>
       <% end %>
 
-      <div class='text-muted'>
+      <div class='text-body-secondary'>
         <small>
           <dl class="list-inline">
             <dt class="list-inline-item m-0"><%= t ".mapper since" %></dt>
       <% end %>
 
       <% if current_user and current_user.administrator? -%>
-        <div class='text-muted'>
+        <div class='text-body-secondary'>
           <small>
             <dl class="list-inline">
               <dt class="list-inline-item m-0"><%= t ".email address" %></dt>
index 340aaf04e2ac7c4604e8322844560f87e4759dde..b7efe912e27e68dea89326de851e2591b1f6e476 100644 (file)
 
 <%= form_tag({ :action => "save" }) do %>
   <!-- legale is <%= @legale %> -->
-  <p class="text-muted"><%= t ".read and accept with tou" %></p>
+  <p class="text-body-secondary"><%= t ".read and accept with tou" %></p>
   <h4>
     <%= t ".heading_ct" %>
   </h4>
-  <p class="text-muted"><%= t ".contributor_terms_explain" %></p>
+  <p class="text-body-secondary"><%= t ".contributor_terms_explain" %></p>
   <label class="form-label">
     <%= t ".legale_select" %>
   </label>
@@ -35,7 +35,7 @@
   </div>
 
   <div>
-    <p id="contributorGuidance" class="text-muted">
+    <p id="contributorGuidance" class="text-body-secondary">
       <%= t ".guidance_info_html",
             :readable_summary_link => link_to(t(".readable_summary"),
                                               "https://www.osmfoundation.org/wiki/License/Contributor_Terms_Summary"),
@@ -55,7 +55,7 @@
   <h4>
     <%= t "layouts.tou" %>
   </h4>
-  <p class="text-muted"><%= t ".tou_explain_html", :tou_link => link_to(t("layouts.tou"), "https://wiki.osmfoundation.org/wiki/Terms_of_Use", :target => :new) %></p>
+  <p class="text-body-secondary"><%= t ".tou_explain_html", :tou_link => link_to(t("layouts.tou"), "https://wiki.osmfoundation.org/wiki/Terms_of_Use", :target => :new) %></p>
 
   <div class="mb-3">
     <div class="form-check">
index b3076b38fe14399a56099ba187b1cb21cac15f09..5ce53e86360117b4f320d7e8f84d4da09edb2769 100644 (file)
@@ -4,22 +4,42 @@
 # See the Securing Rails Applications Guide for more information:
 # https://guides.rubyonrails.org/security.html#content-security-policy-header
 
-# Rails.application.configure do
-#   config.content_security_policy do |policy|
-#     policy.default_src :self, :https
-#     policy.font_src    :self, :https, :data
-#     policy.img_src     :self, :https, :data
-#     policy.object_src  :none
-#     policy.script_src  :self, :https
-#     policy.style_src   :self, :https
-#     # Specify URI for violation reports
-#     # policy.report_uri "/csp-violation-report-endpoint"
-#   end
-#
-#   # Generate session nonces for permitted importmap, inline scripts, and inline styles.
-#   config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s }
-#   config.content_security_policy_nonce_directives = %w(script-src style-src)
-#
-#   # Report violations without enforcing the policy.
-#   # config.content_security_policy_report_only = true
-# end
+Rails.application.configure do
+  connect_src = [:self]
+  img_src = [:self, :data, "www.gravatar.com", "*.wp.com", "tile.openstreetmap.org", "*.tile.thunderforest.com", "tile.tracestrack.com", "*.openstreetmap.fr"]
+  script_src = [:self]
+
+  connect_src << Settings.matomo["location"] if defined?(Settings.matomo)
+  img_src << Settings.matomo["location"] if defined?(Settings.matomo)
+  script_src << Settings.matomo["location"] if defined?(Settings.matomo)
+
+  img_src << Settings.avatar_storage_url if Settings.key?(:avatar_storage_url)
+  img_src << Settings.trace_image_storage_url if Settings.key?(:trace_image_storage_url)
+
+  config.content_security_policy do |policy|
+    policy.default_src :self
+    policy.child_src(:self)
+    policy.connect_src(*connect_src)
+    policy.font_src(:none)
+    policy.form_action(:self)
+    policy.frame_ancestors(:self)
+    policy.frame_src(:self)
+    policy.img_src(*img_src)
+    policy.manifest_src(:self)
+    policy.media_src(:none)
+    policy.object_src(:self)
+    policy.plugin_types
+    policy.script_src(*script_src)
+    policy.style_src(:self)
+    policy.worker_src(:none)
+    policy.manifest_src(:self)
+    policy.report_uri(Settings.csp_report_url) if Settings.key?(:csp_report_url)
+  end
+
+  # Generate session nonces for permitted importmap and inline scripts
+  config.content_security_policy_nonce_generator = ->(_request) { SecureRandom.base64(24) }
+  config.content_security_policy_nonce_directives = %w[style-src]
+
+  # Report violations without enforcing the policy.
+  config.content_security_policy_report_only = true unless Settings.csp_enforce
+end
diff --git a/config/initializers/secure_headers.rb b/config/initializers/secure_headers.rb
deleted file mode 100644 (file)
index 60f1551..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-csp_policy = {
-  :preserve_schemes => true,
-  :default_src => %w['self'],
-  :child_src => %w['self'],
-  :connect_src => %w['self'],
-  :font_src => %w['none'],
-  :form_action => %w['self'],
-  :frame_ancestors => %w['self'],
-  :frame_src => %w['self'],
-  :img_src => %w['self' data: www.gravatar.com *.wp.com tile.openstreetmap.org *.tile.openstreetmap.org *.tile.thunderforest.com tile.tracestrack.com *.openstreetmap.fr],
-  :manifest_src => %w['self'],
-  :media_src => %w['none'],
-  :object_src => %w['self'],
-  :plugin_types => %w[],
-  :script_src => %w['self'],
-  :style_src => %w['self'],
-  :worker_src => %w['none'],
-  :report_uri => []
-}
-
-csp_policy[:connect_src] << Settings.matomo["location"] if defined?(Settings.matomo)
-csp_policy[:img_src] << Settings.matomo["location"] if defined?(Settings.matomo)
-csp_policy[:script_src] << Settings.matomo["location"] if defined?(Settings.matomo)
-
-csp_policy[:img_src] << Settings.avatar_storage_url if Settings.key?(:avatar_storage_url)
-csp_policy[:img_src] << Settings.trace_image_storage_url if Settings.key?(:trace_image_storage_url)
-
-csp_policy[:report_uri] << Settings.csp_report_url if Settings.key?(:csp_report_url)
-
-cookie_policy = {
-  :httponly => { :only => %w[_osm_session _osm_totp_token] }
-}
-
-SecureHeaders::Configuration.default do |config|
-  config.hsts = SecureHeaders::OPT_OUT
-  config.referrer_policy = "strict-origin-when-cross-origin"
-
-  if Settings.csp_enforce
-    config.csp = csp_policy
-    config.csp_report_only = SecureHeaders::OPT_OUT
-  elsif Settings.key?(:csp_report_url)
-    config.csp = SecureHeaders::OPT_OUT
-    config.csp_report_only = csp_policy
-  else
-    config.csp = SecureHeaders::OPT_OUT
-    config.csp_report_only = SecureHeaders::OPT_OUT
-  end
-
-  config.cookies = cookie_policy
-end
index a122848553bf1a9f00fe4d09f2f18ee292617f3b..4119064c39cf1601dbcf5babc877ff06ae953ae1 100644 (file)
@@ -1,7 +1,7 @@
 # Be sure to restart your server when you modify this file.
 
 if Settings.key?(:memcache_servers)
-  Rails.application.config.session_store :mem_cache_store, :memcache_server => Settings.memcache_servers, :namespace => "rails:session", :key => "_osm_session"
+  Rails.application.config.session_store :mem_cache_store, :memcache_server => Settings.memcache_servers, :namespace => "rails:session", :key => "_osm_session", :same_site => :lax
 else
-  Rails.application.config.session_store :cache_store, :key => "_osm_session", :cache => ActiveSupport::Cache::MemoryStore.new
+  Rails.application.config.session_store :cache_store, :key => "_osm_session", :cache => ActiveSupport::Cache::MemoryStore.new, :same_site => :lax
 end