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"
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)
rubocop-rake
sanitize
sass-embedded (~> 1.64.0)
- secure_headers
selenium-webdriver
simplecov
simplecov-lcov
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
$("<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'>")
.on("click", select))
.append(
$("<p>")
- .attr("class", "text-muted")
+ .attr("class", "text-body-secondary")
.text(I18n.t("javascripts.share.paste_html")));
// Geo URI
$("<div>")
.attr("id", "export-warning")
- .attr("class", "text-muted")
+ .attr("class", "text-body-secondary")
.text(I18n.t("javascripts.share.only_standard_layer"))
.appendTo($imageSection);
};
$("<p>")
- .attr("class", "text-muted")
+ .attr("class", "text-body-secondary")
.html(I18n.t("javascripts.share.image_dimensions", args))
.appendTo($form);
/* Utility for de-emphasizing content */
-.text-muted a {
+.text-body-secondary a {
color: $blue;
}
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)
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? ||
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
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"
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]
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
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:
#
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
##
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]
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
end
end
- def embed
- append_content_security_policy_directives(
- :frame_ancestors => %w[*]
- )
- end
+ def embed; end
end
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
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
layout "site"
+ allow_all_form_action :only => :oauth1_authorize
+
def revoke
@token = current_user.oauth_tokens.find_by :token => params[:token]
if @token
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"
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
##
# 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
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
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
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
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
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
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
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
##
# omniauth success callback
def auth_success
+ referer = request.env["omniauth.params"]["referer"]
auth_info = request.env["omniauth.auth"]
provider = auth_info[:provider]
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)
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
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)
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
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
: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
<%= 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>)
<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>)
<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" %>
: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? %>
: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? %>
: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? %>
</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>
<% @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) %>
<% 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>
<%= 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) %>
</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) %>
-<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 %>
-<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 %>">
</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)) %>
</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>
<%= 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) %>
<%= 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),
<% 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 %>
<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>
<%= 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 %>
<% 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'>
<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>
<% 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 %>
<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>
<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>
<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" %>
<% 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">
<%= 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>
<%= 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">
<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) %>
<% 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" %>
<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>
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,
</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>
<%= 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>
</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"),
<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">
# 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
+++ /dev/null
-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
# 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