Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/pull/4455'
Browse files Browse the repository at this point in the history
  • Loading branch information
tomhughes committed May 6, 2024
2 parents 51d7780 + 1874e5b commit b625eef
Show file tree
Hide file tree
Showing 20 changed files with 850 additions and 670 deletions.
23 changes: 23 additions & 0 deletions app/assets/javascripts/auth_providers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//= require qs/dist/qs

$(document).ready(function () {
// Attach referer to authentication buttons
$(".auth_button").each(function () {
var params = Qs.parse(this.search.substring(1));
params.referer = $("#referer").val();
this.search = Qs.stringify(params);
});

// Add click handler to show OpenID field
$("#openid_open_url").click(function (e) {
e.preventDefault();
$("#openid_url").val("http://");
$("#login_auth_buttons").hide().removeClass("d-flex");
$("#login_openid_url").show();
$("#openid_login_button").show();
});

// Hide OpenID field for now
$("#login_openid_url").hide();
$("#openid_login_button").hide();
});
22 changes: 0 additions & 22 deletions app/assets/javascripts/login.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,6 @@
//= qs/dist/qs

$(document).ready(function () {
// Preserve location hash in referer
if (window.location.hash) {
$("#referer").val($("#referer").val() + window.location.hash);
}

// Attach referer to authentication buttons
$(".auth_button").each(function () {
var params = Qs.parse(this.search.substring(1));
params.referer = $("#referer").val();
this.search = Qs.stringify(params);
});

// Add click handler to show OpenID field
$("#openid_open_url").click(function (e) {
e.preventDefault();
$("#openid_url").val("http://");
$("#login_auth_buttons").hide();
$("#login_openid_url").show();
$("#login_openid_submit").show();
});

// Hide OpenID field for now
$("#login_openid_url").hide();
$("#login_openid_submit").hide();
});
16 changes: 5 additions & 11 deletions app/assets/stylesheets/common.scss
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,7 @@ tr.turn {

&.new-user-main {
background-image: image-url("sign-up-illustration.png");
background-position-x: 50px;
}

&.confirm-main {
Expand All @@ -720,17 +721,6 @@ tr.turn {
&.new-user-terms {
background-image: image-url("terms-illustration.png");
}

&.new-user-arm {
height: 110px;
width: 130px;
left: 280px;
top: 180px;
background-image: image-url("sign-up-illustration-arm.png");
position: absolute;
z-index: 100;
pointer-events: none;
}
}

[dir=rtl] .header-illustration {
Expand Down Expand Up @@ -998,6 +988,10 @@ div.secondary-actions {
}
}

.auth-container {
max-width: 600px;
}

/* Rules for tabs inside secondary background sections */

.bg-body-secondary .nav-tabs {
Expand Down
12 changes: 12 additions & 0 deletions app/controllers/concerns/session_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,18 @@ module SessionMethods

private

##
# Read @preferred_auth_provider and @client_app_name from oauth2 authorization request's referer
def parse_oauth_referer(referer)
referer_query = URI(referer).query if referer
return unless referer_query

ref_params = CGI.parse referer_query
preferred = ref_params["preferred_auth_provider"].first
@preferred_auth_provider = preferred if preferred && Settings.key?(:"#{preferred}_auth_id")
@client_app_name = Oauth2Application.where(:uid => ref_params["client_id"].first).pick(:name)
end

##
# return the URL to use for authentication
def auth_url(provider, uid, referer = nil)
Expand Down
2 changes: 2 additions & 0 deletions app/controllers/sessions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ def new
override_content_security_policy_directives(:form_action => []) if Settings.csp_enforce || Settings.key?(:csp_report_url)

session[:referer] = safe_referer(params[:referer]) if params[:referer]

parse_oauth_referer session[:referer]
end

def create
Expand Down
119 changes: 67 additions & 52 deletions app/controllers/users_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ def new
session[:referer]
end

parse_oauth_referer @referer

append_content_security_policy_directives(
:form_action => %w[accounts.google.com *.facebook.com login.live.com github.com meta.wikimedia.org]
)
Expand All @@ -69,13 +71,18 @@ def new
# page, instead send them to the home page
redirect_to @referer || { :controller => "site", :action => "index" }
elsif params.key?(:auth_provider) && params.key?(:auth_uid)
@email_hmac = params[:email_hmac]

self.current_user = User.new(:email => params[:email],
:email_confirmation => params[:email],
:display_name => params[:nickname],
:auth_provider => params[:auth_provider],
:auth_uid => params[:auth_uid])

flash.now[:notice] = render_to_string :partial => "auth_association"
if current_user.valid? || current_user.errors[:email].empty?
flash.now[:notice] = render_to_string :partial => "auth_association"
else
flash.now[:warning] = t ".duplicate_social_email"
end
else
check_signup_allowed

Expand All @@ -91,7 +98,7 @@ def create

Rails.logger.info "create: #{session[:referer]}"

if current_user.auth_provider.present? && current_user.pass_crypt.empty?
if current_user.auth_uid.present?
# We are creating an account with external authentication and
# no password was specified so create a random one
current_user.pass_crypt = SecureRandom.base64(16)
Expand All @@ -108,7 +115,7 @@ def create
else
# Save the user record
session[:new_user] = current_user.slice("email", "display_name", "pass_crypt", "pass_crypt_confirmation")
redirect_to :action => :terms
save_new_user params[:email_hmac]
end
end
end
Expand All @@ -132,7 +139,7 @@ def terms
if current_user&.terms_agreed?
# Already agreed to terms, so just show settings
redirect_to edit_account_path
elsif current_user.nil? && session[:new_user].nil?
elsif current_user.nil?
redirect_to login_path(:referer => request.fullpath)
end
end
Expand Down Expand Up @@ -168,48 +175,6 @@ def save
referer = safe_referer(params[:referer]) if params[:referer]

redirect_to referer || edit_account_path
else
new_user = session.delete(:new_user)
verified_email = new_user.delete("verified_email")

self.current_user = User.new(new_user)

if check_signup_allowed(current_user.email)
current_user.data_public = true
current_user.description = "" if current_user.description.nil?
current_user.creation_ip = request.remote_ip
current_user.languages = http_accept_language.user_preferred_languages
current_user.terms_agreed = Time.now.utc
current_user.tou_agreed = Time.now.utc
current_user.terms_seen = true

if current_user.auth_uid.blank?
current_user.auth_provider = nil
current_user.auth_uid = nil
elsif current_user.email == verified_email
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)

if current_user.status == "active"
session[:referer] = referer
successful_login(current_user)
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

Expand Down Expand Up @@ -266,9 +231,9 @@ def auth_success
elsif session[:new_user]
session[:new_user]["auth_provider"] = provider
session[:new_user]["auth_uid"] = uid
session[:new_user]["verified_email"] = email if email_verified

redirect_to :action => "terms"
email_hmac = UsersController.message_hmac(email) if email_verified && email
save_new_user email_hmac
else
user = User.find_by(:auth_provider => provider, :auth_uid => uid)

Expand All @@ -290,7 +255,8 @@ def auth_success
failed_login t("sessions.new.auth failure")
end
else
redirect_to :action => "new", :nickname => name, :email => email,
email_hmac = UsersController.message_hmac(email) if email_verified && email
redirect_to :action => "new", :nickname => name, :email => email, :email_hmac => email_hmac,
:auth_provider => provider, :auth_uid => uid
end
end
Expand All @@ -306,8 +272,56 @@ def auth_failure
redirect_to origin || login_url
end

def self.message_hmac(text)
sha256 = Digest::SHA256.new
sha256 << Rails.application.key_generator.generate_key("openstreetmap/email_address")
sha256 << text
Base64.urlsafe_encode64(sha256.digest)
end

private

def save_new_user(email_hmac)
new_user = session.delete(:new_user)
self.current_user = User.new(new_user)
if check_signup_allowed(current_user.email)
current_user.data_public = true
current_user.description = "" if current_user.description.nil?
current_user.creation_ip = request.remote_ip
current_user.languages = http_accept_language.user_preferred_languages
current_user.terms_agreed = Time.now.utc
current_user.tou_agreed = Time.now.utc
current_user.terms_seen = true

if current_user.auth_uid.blank?
current_user.auth_provider = nil
current_user.auth_uid = nil
elsif email_hmac && ActiveSupport::SecurityUtils.secure_compare(email_hmac, UsersController.message_hmac(current_user.email))
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)

if current_user.status == "active"
session[:referer] = referer
successful_login(current_user)
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

def welcome_options
uri = URI(session[:referer]) if session[:referer].present?

Expand All @@ -334,9 +348,10 @@ def lookup_user_by_name
##
# return permitted user parameters
def user_params
params.require(:user).permit(:email, :email_confirmation, :display_name,
params.require(:user).permit(:email, :display_name,
:auth_provider, :auth_uid,
:pass_crypt, :pass_crypt_confirmation)
:pass_crypt, :pass_crypt_confirmation,
:consider_pd)
end

##
Expand Down
26 changes: 20 additions & 6 deletions app/helpers/user_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,19 +53,33 @@ def user_image_url(user, options = {})
# External authentication support

def openid_logo
image_tag "openid_small.png", :alt => t("sessions.new.openid_logo_alt"), :class => "align-text-bottom"
image_tag "openid_small.png", :alt => t("application.auth_providers.openid_logo_alt"), :class => "align-text-bottom"
end

def auth_button(name, provider, options = {})
link_to(
image_tag("#{name}.svg",
:alt => t("sessions.new.auth_providers.#{name}.alt"),
:class => "rounded-3",
:size => "36"),
:alt => t("application.auth_providers.#{name}.alt"),
:class => "rounded-1",
:size => "24"),
auth_path(options.merge(:provider => provider)),
:method => :post,
:class => "auth_button",
:title => t("sessions.new.auth_providers.#{name}.title")
:class => "auth_button p-2 d-block",
:title => t("application.auth_providers.#{name}.title")
)
end

def auth_button_preferred(name, provider, options = {})
link_to(
image_tag("#{name}.svg",
:alt => t("application.auth_providers.#{name}.alt"),
:class => "rounded-1 me-3",
:width => "24px",
:height => "24px") + 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",
:title => t("application.auth_providers.#{name}.title")
)
end

Expand Down
2 changes: 1 addition & 1 deletion app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ class User < ApplicationRecord
:whitespace => { :leading => false, :trailing => false },
:width => { :minimum => 3 }
validate :display_name_cannot_be_user_id_with_other_id, :if => proc { |u| u.display_name_changed? }
validates :email, :presence => true, :confirmation => true, :characters => true
validates :email, :presence => true, :characters => true
validates :email, :if => proc { |u| u.email_changed? },
:uniqueness => { :case_sensitive => false }
validates :email, :if => proc { |u| u.email_changed? },
Expand Down
Loading

0 comments on commit b625eef

Please sign in to comment.