diff --git a/Gemfile b/Gemfile index ff658fde3..1bea45cc0 100644 --- a/Gemfile +++ b/Gemfile @@ -17,6 +17,7 @@ gem 'font-awesome-rails', '~> 4.7.0.2' gem 'recaptcha', require: 'recaptcha/rails' gem 'sanitize', '~> 4.4' gem 'omniauth' +gem 'omniauth-linkedin-oauth2' # Gems for API implementation gem 'jwt', '~> 1.5' diff --git a/app/assets/images/linkedin/Sign-in-Small---Active.png b/app/assets/images/linkedin/Sign-in-Small---Active.png new file mode 100644 index 000000000..dea692fd9 Binary files /dev/null and b/app/assets/images/linkedin/Sign-in-Small---Active.png differ diff --git a/app/assets/images/linkedin/Sign-in-Small---Default.png b/app/assets/images/linkedin/Sign-in-Small---Default.png new file mode 100644 index 000000000..f8129afe2 Binary files /dev/null and b/app/assets/images/linkedin/Sign-in-Small---Default.png differ diff --git a/app/assets/images/linkedin/Sign-in-Small---Hover.png b/app/assets/images/linkedin/Sign-in-Small---Hover.png new file mode 100644 index 000000000..643236eec Binary files /dev/null and b/app/assets/images/linkedin/Sign-in-Small---Hover.png differ diff --git a/app/controllers/users/omniauth_callbacks_controller.rb b/app/controllers/users/omniauth_callbacks_controller.rb index 27b884710..7b0bff2b9 100644 --- a/app/controllers/users/omniauth_callbacks_controller.rb +++ b/app/controllers/users/omniauth_callbacks_controller.rb @@ -1,6 +1,10 @@ module Users class OmniauthCallbacksController < Devise::OmniauthCallbacksController + include UsersGenerator + skip_before_action :verify_authenticity_token + before_action :sign_up_with_provider_enabled?, + only: :linkedin # You should configure your model like this: # devise :omniauthable, omniauth_providers: [:twitter] @@ -9,6 +13,55 @@ module Users # def twitter # end + def linkedin + auth_hash = request.env['omniauth.auth'] + + @user = User.from_omniauth(auth_hash) + if @user && @user.current_team_id? + # User already exists and has been signed up with LinkedIn; just sign in + set_flash_message(:notice, + :success, + kind: I18n.t('devise.linkedin.provider_name')) + sign_in_and_redirect @user + elsif @user + # User already exists and has started sign up with LinkedIn; + # but doesn't have team (needs to complete sign up - agrees to TOS) + set_flash_message(:alert, + :failure, + kind: I18n.t('devise.linkedin.provider_name'), + reason: I18n.t('devise.linkedin.complete_sign_up')) + redirect_to users_sign_up_provider_path(user: @user) + elsif User.find_by_email(auth_hash['info']['email']) + # email is already taken, so sign up with Linked in is not allowed + set_flash_message(:alert, + :failure, + kind: I18n.t('devise.linkedin.provider_name'), + reason: I18n.t('devise.linkedin.email_already_taken', + email: auth_hash['info']['email'])) + redirect_to after_omniauth_failure_path_for(resource_name) + else + # Create new user and identity; and redirect to complete sign up form + @user = User.new( + full_name: auth_hash['info']['name'], + initials: generate_initials(auth_hash['info']['name']), + email: auth_hash['info']['email'], + password: generate_user_password + ) + @user.avatar_remote_url = (auth_hash['info']['image']) + user_identity = UserIdentity.new(user: @user, + provider: auth_hash['provider'], + uid: auth_hash['uid']) + unless @user.save && user_identity.save + set_flash_message(:alert, + :failure, + kind: I18n.t('devise.linkedin.provider_name'), + reason: I18n.t('devise.linkedin.failed_to_save')) + redirect_to after_omniauth_failure_path_for(resource_name) and return + end + redirect_to users_sign_up_provider_path(user: @user) + end + end + # More info at: # https://github.com/plataformatec/devise#omniauth @@ -28,5 +81,18 @@ module Users # def after_omniauth_failure_path_for(scope) # super(scope) # end + + private + + def sign_up_with_provider_enabled? + render_403 unless Rails.configuration.x.enable_user_registration + render_403 unless Rails.configuration.x.linkedin_signin_enabled + end + + def generate_initials(full_name) + initials = full_name.titleize.scan(/[A-Z]+/).join + initials = initials.strip.empty? ? 'PLCH' : initials[0..3] + initials + end end end diff --git a/app/controllers/users/registrations_controller.rb b/app/controllers/users/registrations_controller.rb index dbda51b4a..f127dfd13 100644 --- a/app/controllers/users/registrations_controller.rb +++ b/app/controllers/users/registrations_controller.rb @@ -1,5 +1,9 @@ class Users::RegistrationsController < Devise::RegistrationsController prepend_before_action :check_captcha, only: [:create] + before_action :registration_enabled?, + only: %i(new create new_with_provider create_with_provider) + before_action :sign_up_with_provider_enabled?, + only: %i(new_with_provider create_with_provider) def avatar user = User.find_by_id(params[:id]) || current_user @@ -122,12 +126,9 @@ class Users::RegistrationsController < Devise::RegistrationsController end end - def new - render_403 && return unless Rails.configuration.x.enable_user_registration - end + def new; end def create - render_403 && return unless Rails.configuration.x.enable_user_registration build_resource(sign_up_params) valid_resource = resource.valid? # ugly checking if new team on sign up is enabled :( @@ -174,6 +175,36 @@ class Users::RegistrationsController < Devise::RegistrationsController end end + def new_with_provider; end + + def create_with_provider + @user = User.find_by_id(user_provider_params['user']) + # Create new team for the new user + @team = Team.new(team_provider_params) + @team.validate + + if @team.valid? && Rails.configuration.x.new_team_on_signup + # Set the confirmed_at == created_at IF not using email confirmations + unless Rails.configuration.x.enable_email_confirmations + @user.update!(confirmed_at: @user.created_at) + end + + @team.created_by = @user # set created_by for team + @team.save! + + # Add this user to the team as owner + UserTeam.create(user: @user, team: @team, role: :admin) + + # set current team to new user + @user.current_team_id = @team.id + @user.save! + + sign_in_and_redirect @user + else + render :new_with_provider + end + end + protected # Called upon creating User (before .save). Permits parameters and extracts @@ -191,6 +222,14 @@ class Users::RegistrationsController < Devise::RegistrationsController tmp.merge(:initials => initials) end + def team_provider_params + params.require(:team).permit(:name) + end + + def user_provider_params + params.permit(:user) + end + def account_update_params params.require(:user).permit( :full_name, @@ -268,6 +307,14 @@ class Users::RegistrationsController < Devise::RegistrationsController end end + def registration_enabled? + render_403 unless Rails.configuration.x.enable_user_registration + end + + def sign_up_with_provider_enabled? + render_403 unless Rails.configuration.x.linkedin_signin_enabled + end + # Redirect to login page after signing up def after_sign_up_path_for(resource) new_user_session_path diff --git a/app/models/user.rb b/app/models/user.rb index e9265fbc6..cca3b9409 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -217,6 +217,14 @@ class User < ApplicationRecord self.full_name = name end + def avatar_remote_url=(url_value) + self.avatar = URI.parse(url_value) + # Assuming url_value is http://example.com/photos/face.png + # avatar_file_name == "face.png" + # avatar_content_type == "image/png" + @avatar_remote_url = url_value + end + def current_team Team.find_by_id(self.current_team_id) end diff --git a/app/views/users/registrations/new_with_provider.html.erb b/app/views/users/registrations/new_with_provider.html.erb new file mode 100644 index 000000000..2feddd300 --- /dev/null +++ b/app/views/users/registrations/new_with_provider.html.erb @@ -0,0 +1,37 @@ +<% provide(:head_title, t('users.registrations.new.head_title')) %> + +