Skip to content

Commit

Permalink
Split create function into two login paths (publiclab#3883)
Browse files Browse the repository at this point in the history
* Split create function into two login paths

* Ensure preservation of return_to through OAuth login flow (publiclab#3884)
  • Loading branch information
Radhikadua123 authored and jywarren committed Nov 10, 2018
1 parent 7e83a73 commit 929f50f
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 166 deletions.
251 changes: 131 additions & 120 deletions app/controllers/user_sessions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,141 +7,152 @@ def new
def create
auth = request.env['omniauth.auth']
if auth
# Find an identity here
@identity = UserTag.find_with_omniauth(auth)
# User successfully completed oauth signin on third-party
handle_social_login_flow(auth)
else
# User clicked on login button on site
handle_site_login_flow
end
end

def handle_social_login_flow(auth)
# Find an identity here
@identity = UserTag.find_with_omniauth(auth)
return_to = request.env['omniauth.origin'] || root_url

if signed_in?
if @identity.nil?
if signed_in?
if @identity.nil?
# If no identity was found, create a brand new one here
@identity = UserTag.create_with_omniauth(auth, current_user.id)
# The identity is not associated with the current_user so lets
# associate the identity
@identity.user = current_user
@identity.save
redirect_to return_to, notice: "Successfully linked to your account!"
elsif @identity.user == current_user
# User is signed in so they are trying to link an identity with their
# account. But we found the identity and the user associated with it
# is the current user. So the identity is already associated with
# this user. So let's display an error message.
redirect_to return_to, notice: "Already linked to your account!"
else
# User is signed in so they are trying to link an identity with their
# account. But we found the identity and a different user associated with it
# ,which is not the current user. So the identity is already associated with
# that user. So let's display an error message.
redirect_to return_to, notice: "Already linked to another account!"
end
else # not signed in
if @identity&.user.present?
# The identity we found had a user associated with it so let's
# just log them in here
@user = @identity.user
@user_session = UserSession.create(@identity.user)
redirect_to return_to, notice: "Signed in!"
else # identity does not exist so we need to either create a user with identity OR link identity to existing user
if User.where(email: auth["info"]["email"]).empty?
# Create a new user as email provided is not present in PL database
user = User.create_with_omniauth(auth)
WelcomeMailer.notify_newcomer(user).deliver_now
@identity = UserTag.create_with_omniauth(auth, user.id)
key = user.generate_reset_key
@user_session = UserSession.create(@identity.user)
@user = user
# send key to user email
PasswordResetMailer.reset_notify(user, key).deliver_now unless user.nil? # respond the same to both successes and failures; security
redirect_to return_to, notice: "You have successfully signed in. Please change your password via a link sent to you via e-mail"
else # email exists so link the identity with existing user and log in the user
user = User.where(email: auth["info"]["email"])
# If no identity was found, create a brand new one here
@identity = UserTag.create_with_omniauth(auth, current_user.id)
@identity = UserTag.create_with_omniauth(auth, user.ids.first)
# The identity is not associated with the current_user so lets
# associate the identity
@identity.user = current_user
@identity.save
redirect_to root_url, notice: "Successfully linked to your account!"
elsif @identity.user == current_user
# User is signed in so they are trying to link an identity with their
# account. But we found the identity and the user associated with it
# is the current user. So the identity is already associated with
# this user. So let's display an error message.
redirect_to root_url, notice: "Already linked to your account!"
else
# User is signed in so they are trying to link an identity with their
# account. But we found the identity and a different user associated with it
# ,which is not the current user. So the identity is already associated with
# that user. So let's display an error message.
redirect_to root_url, notice: "Already linked to another account!"
end
else # not signed in
if @identity&.user.present?
# The identity we found had a user associated with it so let's
# just log them in here
@user = @identity.user
@user = user
# log in them
@user_session = UserSession.create(@identity.user)
redirect_to root_url, notice: "Signed in!"
else # identity does not exist so we need to either create a user with identity OR link identity to existing user
if User.where(email: auth["info"]["email"]).empty?
# Create a new user as email provided is not present in PL database
user = User.create_with_omniauth(auth)
WelcomeMailer.notify_newcomer(user).deliver_now
@identity = UserTag.create_with_omniauth(auth, user.id)
key = user.generate_reset_key
@user_session = UserSession.create(@identity.user)
@user = user
# send key to user email
PasswordResetMailer.reset_notify(user, key).deliver_now unless user.nil? # respond the same to both successes and failures; security
redirect_to root_url, notice: "You have successfully signed in. Please change your password via a link sent to you via e-mail"
else # email exists so link the identity with existing user and log in the user
user = User.where(email: auth["info"]["email"])
# If no identity was found, create a brand new one here
@identity = UserTag.create_with_omniauth(auth, user.ids.first)
# The identity is not associated with the current_user so lets
# associate the identity
@identity.save
@user = user
# log in them
@user_session = UserSession.create(@identity.user)
redirect_to root_url, notice: "Successfully linked to your account!"
end
redirect_to return_to, notice: "Successfully linked to your account!"
end
end
end
end

def handle_site_login_flow
username = params[:user_session][:username] if params[:user_session]
u = User.find_by(username: username)
if u && u.password_checker != 0
n = u.password_checker
hash = { 1 => "Facebook", 2 => "Github", 3 => "Google", 4 => "Twitter" }
s = "This account doesn't have a password set. It may be logged in with " + hash[n] + " account, or you can set a new password via Forget password feature"
flash[:error] = s
redirect_to '/'
else
username = params[:user_session][:username] if params[:user_session]
u = User.find_by(username: username)
if u && u.password_checker != 0
n = u.password_checker
hash = { 1 => "Facebook", 2 => "Github", 3 => "Google", 4 => "Twitter" }
s = "This account doesn't have a password set. It may be logged in with " + hash[n] + " account, or you can set a new password via Forget password feature"
flash[:error] = s
redirect_to '/'
else
params[:user_session][:username] = params[:openid] if params[:openid] # second runthrough must preserve username
@user = User.find_by(username: username)
# try finding by email, if that exists
if @user.nil? && !User.where(email: username).empty?
@user = User.find_by(email: username)
params[:user_session][:username] = @user.username
end
if @user.nil?
flash[:warning] = "There is nobody in our system by that name, are you sure you have the right username?"
redirect_to '/login'
elsif params[:user_session].nil? || @user&.drupal_user&.status == 1
# an existing Rails user
if params[:user_session].nil? || @user
if @user&.crypted_password.nil? # the user has not created a pwd in the new site
params[:user_session][:openid_identifier] = 'https://old.publiclab.org/people/' + username + '/identity' if username
params[:user_session].delete(:password)
params[:user_session].delete(:username)
params[:openid] = username # pack up username for second runthrough
end
@user_session = UserSession.new(username: params[:user_session][:username],
password: params[:user_session][:password],
remember_me: params[:user_session][:remember_me])
saved = @user_session.save do |result|
if result
# replace this with temporarily saving pwd in session,
# and automatically saving it in the user record after login is completed
if current_user.crypted_password.nil? # the user has not created a pwd in the new site
flash[:warning] = I18n.t('user_sessions_controller.create_password_for_new_site')
redirect_to '/profile/edit'
params[:user_session][:username] = params[:openid] if params[:openid] # second runthrough must preserve username
@user = User.find_by(username: username)
# try finding by email, if that exists
if @user.nil? && !User.where(email: username).empty?
@user = User.find_by(email: username)
params[:user_session][:username] = @user.username
end
if @user.nil?
flash[:warning] = "There is nobody in our system by that name, are you sure you have the right username?"
redirect_to '/login'
elsif params[:user_session].nil? || @user&.drupal_user&.status == 1
# an existing Rails user
if params[:user_session].nil? || @user
if @user&.crypted_password.nil? # the user has not created a pwd in the new site
params[:user_session][:openid_identifier] = 'https://old.publiclab.org/people/' + username + '/identity' if username
params[:user_session].delete(:password)
params[:user_session].delete(:username)
params[:openid] = username # pack up username for second runthrough
end
@user_session = UserSession.new(username: params[:user_session][:username],
password: params[:user_session][:password],
remember_me: params[:user_session][:remember_me])
saved = @user_session.save do |result|
if result
# replace this with temporarily saving pwd in session,
# and automatically saving it in the user record after login is completed
if current_user.crypted_password.nil? # the user has not created a pwd in the new site
flash[:warning] = I18n.t('user_sessions_controller.create_password_for_new_site')
redirect_to '/profile/edit'
else
flash[:notice] = I18n.t('user_sessions_controller.logged_in')
if session[:openid_return_to] # for openid login, redirects back to openid auth process
return_to = session[:openid_return_to]
session[:openid_return_to] = nil
redirect_to return_to
elsif session[:return_to]
return_to = session[:return_to]
session[:return_to] = nil
redirect_to return_to
elsif params[:return_to]
redirect_to params[:return_to]
else
flash[:notice] = I18n.t('user_sessions_controller.logged_in')
if session[:openid_return_to] # for openid login, redirects back to openid auth process
return_to = session[:openid_return_to]
session[:openid_return_to] = nil
redirect_to return_to
elsif session[:return_to]
return_to = session[:return_to]
session[:return_to] = nil
redirect_to return_to
elsif params[:return_to]
redirect_to params[:return_to]
else
redirect_to '/dashboard'
end
redirect_to '/dashboard'
end
else
# Login failed; probably bad password.
# Errors will display on login form:
render action: 'new'
end
else
# Login failed; probably bad password.
# Errors will display on login form:
render action: 'new'
end
else # not a native user
if !DrupalUser.find_by(name: username).nil?
# this is a user from the old site who hasn't registered on the new site
redirect_to controller: :users, action: :create, user: { openid_identifier: username }
else # totally new user!
flash[:warning] = I18n.t('user_sessions_controller.sign_up_to_join')
redirect_to '/signup'
end
end
elsif params[:user_session].nil? || @user&.drupal_user&.status == 5
flash[:error] = I18n.t('user_sessions_controller.user_has_been_moderated', username: @user.username).html_safe
redirect_to '/'
else
flash[:error] = I18n.t('user_sessions_controller.user_has_been_banned', username: @user.username).html_safe
redirect_to '/'
else # not a native user
if !DrupalUser.find_by(name: username).nil?
# this is a user from the old site who hasn't registered on the new site
redirect_to controller: :users, action: :create, user: { openid_identifier: username }
else # totally new user!
flash[:warning] = I18n.t('user_sessions_controller.sign_up_to_join')
redirect_to '/signup'
end
end
elsif params[:user_session].nil? || @user&.drupal_user&.status == 5
flash[:error] = I18n.t('user_sessions_controller.user_has_been_moderated', username: @user.username).html_safe
redirect_to '/'
else
flash[:error] = I18n.t('user_sessions_controller.user_has_been_banned', username: @user.username).html_safe
redirect_to '/'
end
end
end
Expand Down
45 changes: 3 additions & 42 deletions app/views/layouts/_header.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
<% end %>
</h5>
</div>

<li><a href="/profile/<%= current_user.username %>"><%= t('layout._header.profile') %></a></li>
<li><a href="/profile/edit"><%= t('layout._header.edit_profile') %></a></li>
<li><a href="/settings" >Email Settings</a></li>
Expand All @@ -121,48 +121,9 @@
<li><a href="/logoutRemotely">Logout from all devices</a></li>
</ul>
<% else %>
<a class="hidden-sm" href="#" class="dropdown-toggle" data-toggle="dropdown">
<%= t('layout._header.login.login_title') %>
<a href="/login?return_to=<%= params[:return_to] || request.path %>">
<%= t('layout._header.login.login_title') %>
</a>
<ul id="login-dropdown" class="dropdown-menu" style="width:245px; color: white;">
<li style="padding:6px;">
<%= form_for :user_session, :as => :user_session, :url => { :controller => "user_sessions", :action => "create" }, :html => {:class => "form"} do |f| %>
<div class="form-group">
<% if Rails.env == "production" %>
<label style="display: block; text-align: center;">Log In with</label>
<div class="loginbutton" style="float:left">
<%= render :partial => "layouts/social_icons" %>
</div>
<br style="clear:both;"/>
<label style="display: block; text-align: center; margin-top:13px;">OR</label>
<% end %>
</div>
<form>
<div class="form-group">
<label for="username"><%= t('layout._header.login.username') %></label>
<%= f.text_field :username, { tabindex: 1, class: 'form-control', id: 'username-login' } %>
</div>
<div class="form-group">
<label for="password"><%= t('layout._header.login.password') %></label>
<%= f.password_field :password, { tabindex: 2, class: 'form-control', id: 'password-login' } %>
</div>
<input type="hidden" name="return_to" value="<%= params[:return_to] || request.path %>" />
<div class="form-check float-right">
<label>
<%= f.check_box :remember_me %> <%= t('layout._header.login.remember_me') %>
</label>
</div>
<div class="form-group">
<button class="btn btn-primary" type="submit" tabindex="3"><%= t('layout._header.login.login_title') %></button>
<button class="btn btn-default" href="/signup" tabindex="4"><%= t('layout._header.login.sign_up') %></button>
</div>
<div>
<a href="/reset/"><%= t('layout._header.login.reset_password') %></a>
</div>
</form>
<% end %>
</li>
</ul>
<% end %>
<% end %>
</li>
Expand Down
24 changes: 20 additions & 4 deletions app/views/layouts/_social_icons.html.erb
Original file line number Diff line number Diff line change
@@ -1,4 +1,20 @@
<a href="/auth/google_oauth2" id="connect-google"><span class="btn btn-default" style="margin-right:2px;background-color: #d34836;"><i class="fa fa-google fa-fw" style="font-size:20px;color:white;"></i></span></a>
<a href="/auth/github" id="connect-github"><span class="btn btn-default" style="margin-left:2px;background-color: #333;"><i class="fa fa-github fa-fw" style="font-size:20px;color:white;"></i></span></a>
<a href="https://publiclab.org/auth/twitter" id="connect-twitter"><span class="btn btn-default" style="margin-left:2px;background-color: #1da1f2;"><i class="fa fa-twitter fa-fw" style="font-size:20px;color:white;margin-left:2px;"></i></span></a>
<a href="/auth/facebook" id="connect-facebook"><span class="btn btn-default" style="margin-left:2px;background-color: #3b5998"><i class="fa fa-facebook fa-fw" style="font-size:20px;color:white;"></i></span></a>
<a href="/auth/google_oauth2?origin=<%= params[:return_to] || root_url %>" id="connect-google">
<span class="btn btn-default" style="margin-right:2px;background-color: #d34836;">
<i class="fa fa-google fa-fw" style="font-size:20px;color:white;"></i>
</span>
</a>
<a href="/auth/github?origin=<%= params[:return_to] || root_url %>" id="connect-github">
<span class="btn btn-default" style="margin-left:2px;background-color: #333;">
<i class="fa fa-github fa-fw" style="font-size:20px;color:white;"></i>
</span>
</a>
<a href="/auth/twitter?origin=<%= params[:return_to] || root_url %>" id="connect-twitter">
<span class="btn btn-default" style="margin-left:2px;background-color: #1da1f2;">
<i class="fa fa-twitter fa-fw" style="font-size:20px;color:white;margin-left:2px;"></i>
</span>
</a>
<a href="/auth/facebook?origin=<%= params[:return_to] || root_url %>" id="connect-facebook">
<span class="btn btn-default" style="margin-left:2px;background-color: #3b5998">
<i class="fa fa-facebook fa-fw" style="font-size:20px;color:white;"></i>
</span>
</a>

0 comments on commit 929f50f

Please sign in to comment.