kanbanworkflowstimelinescrumrubyroadmapproject-planningproject-managementopenprojectangularissue-trackerifcgantt-chartganttbug-trackerboardsbcf
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
196 lines
6.0 KiB
196 lines
6.0 KiB
#-- copyright
|
|
# OpenProject is a project management system.
|
|
# Copyright (C) 2012-2018 the OpenProject Foundation (OPF)
|
|
#
|
|
# This program is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU General Public License version 3.
|
|
#
|
|
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
|
# Copyright (C) 2006-2017 Jean-Philippe Lang
|
|
# Copyright (C) 2010-2013 the ChiliProject Team
|
|
#
|
|
# This program is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU General Public License
|
|
# as published by the Free Software Foundation; either version 2
|
|
# of the License, or (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
#
|
|
# See docs/COPYRIGHT.rdoc for more details.
|
|
#++
|
|
|
|
require 'uri'
|
|
|
|
##
|
|
# Intended to be used by the AccountController to handle omniauth logins
|
|
module Concerns::OmniauthLogin
|
|
extend ActiveSupport::Concern
|
|
|
|
included do
|
|
# disable CSRF protection since that should be covered by the omniauth strategy
|
|
# the other filters are not applicable either since OmniAuth is doing authentication
|
|
# itself
|
|
[
|
|
:verify_authenticity_token, :user_setup,
|
|
:check_if_login_required, :check_session_lifetime
|
|
]
|
|
.each { |key| skip_before_action key, only: [:omniauth_login] }
|
|
|
|
helper :omniauth
|
|
end
|
|
|
|
def omniauth_login
|
|
auth_hash = request.env['omniauth.auth']
|
|
|
|
return render_400 unless auth_hash.valid?
|
|
|
|
# Set back url to page the omniauth login link was clicked on
|
|
params[:back_url] = request.env['omniauth.origin']
|
|
|
|
user =
|
|
if session.include? :invitation_token
|
|
tok = Token::Invitation.find_by value: session[:invitation_token]
|
|
u = tok.user
|
|
u.identity_url = identity_url_from_omniauth(auth_hash)
|
|
tok.destroy
|
|
session.delete :invitation_token
|
|
u
|
|
else
|
|
User.find_or_initialize_by identity_url: identity_url_from_omniauth(auth_hash)
|
|
end
|
|
|
|
decision = OpenProject::OmniAuth::Authorization.authorized? auth_hash
|
|
if decision.approve?
|
|
authorization_successful user, auth_hash
|
|
else
|
|
authorization_failed user, decision.message
|
|
end
|
|
end
|
|
|
|
def omniauth_failure
|
|
logger.warn(params[:message]) if params[:message]
|
|
show_error I18n.t(:error_external_authentication_failed)
|
|
end
|
|
|
|
def direct_login_provider_url(params = {})
|
|
omniauth_start_url(direct_login_provider, params)
|
|
end
|
|
|
|
private
|
|
|
|
def authorization_successful(user, auth_hash)
|
|
if user.new_record? || user.invited?
|
|
create_user_from_omniauth user, auth_hash
|
|
else
|
|
if user.active?
|
|
user.log_successful_login
|
|
OpenProject::OmniAuth::Authorization.after_login! user, auth_hash, self
|
|
end
|
|
login_user_if_active(user)
|
|
end
|
|
end
|
|
|
|
def authorization_failed(user, error)
|
|
logger.warn "Authorization for User #{user.id} failed: #{error}"
|
|
show_error error
|
|
end
|
|
|
|
def show_error(error)
|
|
flash[:error] = error
|
|
redirect_to action: 'login'
|
|
end
|
|
|
|
# a user may login via omniauth and (if that user does not exist
|
|
# in our database) will be created using this method.
|
|
def create_user_from_omniauth(user, auth_hash)
|
|
# Self-registration off
|
|
return self_registration_disabled unless Setting.self_registration?
|
|
|
|
fill_user_fields_from_omniauth user, auth_hash
|
|
|
|
opts = {
|
|
omni_auth_hash: auth_hash
|
|
}
|
|
|
|
# Create on the fly
|
|
register_user_according_to_setting(user, opts) do
|
|
# Allow registration form to show provider-specific title
|
|
@omniauth_strategy = auth_hash[:provider]
|
|
|
|
# Store a timestamp so we can later make sure that authentication information can
|
|
# only be reused for a short time.
|
|
session_info = auth_hash.merge(omniauth: true, timestamp: Time.new)
|
|
|
|
onthefly_creation_failed(user, session_info)
|
|
end
|
|
end
|
|
|
|
def register_via_omniauth(user, session, permitted_params)
|
|
auth = session[:auth_source_registration]
|
|
return if handle_omniauth_registration_expired(auth)
|
|
|
|
fill_user_fields_from_omniauth(user, auth)
|
|
user.update_attributes(permitted_params.user_register_via_omniauth)
|
|
|
|
opts = {
|
|
omni_auth_hash: auth
|
|
}
|
|
register_user_according_to_setting user, opts
|
|
end
|
|
|
|
def fill_user_fields_from_omniauth(user, auth)
|
|
user.update_attributes omniauth_hash_to_user_attributes(auth)
|
|
user.register unless user.invited?
|
|
user
|
|
end
|
|
|
|
def omniauth_hash_to_user_attributes(auth)
|
|
info = auth[:info]
|
|
|
|
attribute_map = {
|
|
login: info[:email],
|
|
mail: info[:email],
|
|
firstname: info[:first_name] || info[:name],
|
|
lastname: info[:last_name],
|
|
identity_url: identity_url_from_omniauth(auth)
|
|
}
|
|
|
|
# Allow strategies to override mapping
|
|
strategy = request.env['omniauth.strategy']
|
|
if strategy.respond_to?(:omniauth_hash_to_user_attributes)
|
|
attribute_map.merge(strategy.omniauth_hash_to_user_attributes(auth))
|
|
else
|
|
attribute_map
|
|
end
|
|
end
|
|
|
|
def identity_url_from_omniauth(auth)
|
|
"#{auth[:provider]}:#{auth[:uid]}"
|
|
end
|
|
|
|
# if the omni auth registration happened too long ago,
|
|
# we don't accept it anymore.
|
|
def handle_omniauth_registration_expired(auth)
|
|
if auth['timestamp'] < Time.now - 30.minutes
|
|
flash[:error] = I18n.t(:error_omniauth_registration_timed_out)
|
|
redirect_to(signin_url)
|
|
end
|
|
end
|
|
|
|
def self.url_with_params(url, params = {})
|
|
URI.parse(url).tap do |uri|
|
|
query = URI.decode_www_form(uri.query || '')
|
|
params.each do |key, value|
|
|
query << [key, value]
|
|
end
|
|
uri.query = URI.encode_www_form(query) unless query.empty?
|
|
end.to_s
|
|
end
|
|
end
|
|
|