Skip to content
Snippets Groups Projects
Commit 3a5ed526 authored by Valery Sizov's avatar Valery Sizov
Browse files

Supporting for multiple omniauth provider for the same user

parent 1a80d13a
No related branches found
No related tags found
1 merge request!8686add "Uplaod" and "Replace" functionality
Showing
with 123 additions and 127 deletions
Loading
Loading
@@ -51,7 +51,6 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
 
# Only allow properly saved users to login.
if @user.persisted? && @user.valid?
# binding.pry
sign_in_and_redirect(@user.gl_user)
else
error_message =
Loading
Loading
@@ -66,8 +65,8 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
redirect_to omniauth_error_path(oauth['provider'], error: error_message) and return
end
end
rescue StandardError
flash[:notice] = "There's no such user!"
rescue ForbiddenAction => e
flash[:notice] = e.message
redirect_to new_user_session_path
end
 
Loading
Loading
Loading
Loading
@@ -10,10 +10,10 @@ module ProfileHelper
end
 
def show_profile_social_tab?
enabled_social_providers.any? && !current_user.ldap_user?
enabled_social_providers.any?
end
 
def show_profile_remove_tab?
gitlab_config.signup_enabled && !current_user.ldap_user?
gitlab_config.signup_enabled
end
end
Loading
Loading
@@ -2,6 +2,4 @@ class Identity < ActiveRecord::Base
belongs_to :user
 
validates :extern_uid, allow_blank: true, uniqueness: {scope: :provider}
scope :ldap, -> { where('provider LIKE ?', 'ldap%') }
end
\ No newline at end of file
Loading
Loading
@@ -406,7 +406,11 @@ class User < ActiveRecord::Base
end
 
def ldap_user?
extern_uid && provider.start_with?('ldap')
identities.exists?(["provider LIKE ? AND extern_uid IS NOT NULL", "ldap%"])
end
def ldap_identity
@ldap_identity ||= identities.find_by(["provider LIKE ?", "ldap%"])
end
 
def accessible_deploy_keys
Loading
Loading
Loading
Loading
@@ -107,7 +107,7 @@ class NotificationService
# Notify new user with email after creation
def new_user(user, token = nil)
# Don't email omniauth created users
mailer.new_user_email(user.id, token) unless user.extern_uid?
mailer.new_user_email(user.id, token) unless user.identities.any?
end
 
# Notify users on new note in system
Loading
Loading
Loading
Loading
@@ -95,7 +95,7 @@
%li
%span.light LDAP uid:
%strong
= @user.extern_uid
= @user.ldap_identity.extern_uid
 
- if @user.created_by
%li
Loading
Loading
- providers = (enabled_oauth_providers - [:ldap])
- providers = enabled_oauth_providers.reject{|provider| provider.to_s.starts_with?('ldap')}
- if providers.present?
.bs-callout.bs-callout-info{:'data-no-turbolink' => 'data-no-turbolink'}
%span Sign in with: &nbsp;
Loading
Loading
Loading
Loading
@@ -8,14 +8,25 @@ class AddIdentityTable < ActiveRecord::Migration
 
add_index :identities, :user_id
 
User.where("provider is not NULL").find_each do |user|
User.where("provider IS NOT NULL").find_each do |user|
execute "INSERT INTO identities(provider, extern_uid, user_id) VALUES('#{user.provider}', '#{user.extern_uid}', '#{user.id}')"
end
 
#TODO remove user's columns extern_uid and provider
remove_column :users, :extern_uid
remove_column :users, :provider
end
 
def down
#TODO
add_column :users, :extern_uid, :string
add_column :users, :provider, :string
User.where("id IN(SELECT user_id FROM identities)").find_each do |user|
identity = user.identities.last
user.extern_uid = identity.extern_uid
user.provider = identity.provider
user.save
end
drop_table :identities
end
end
Loading
Loading
@@ -16,15 +16,6 @@ ActiveRecord::Schema.define(version: 20141121161704) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
 
create_table "appearances", force: true do |t|
t.string "title"
t.text "description"
t.string "logo"
t.integer "updated_by"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "broadcast_messages", force: true do |t|
t.text "message", null: false
t.datetime "starts_at"
Loading
Loading
@@ -83,21 +74,6 @@ ActiveRecord::Schema.define(version: 20141121161704) do
 
add_index "forked_project_links", ["forked_to_project_id"], name: "index_forked_project_links_on_forked_to_project_id", unique: true, using: :btree
 
create_table "git_hooks", force: true do |t|
t.string "force_push_regex"
t.string "delete_branch_regex"
t.string "commit_message_regex"
t.boolean "deny_delete_tag"
t.integer "project_id"
t.datetime "created_at"
t.datetime "updated_at"
t.string "username_regex"
t.string "email_regex"
t.string "author_email_regex"
t.boolean "member_check", default: false, null: false
t.string "file_name_regex"
end
create_table "identities", force: true do |t|
t.string "extern_uid"
t.string "provider"
Loading
Loading
@@ -162,15 +138,6 @@ ActiveRecord::Schema.define(version: 20141121161704) do
 
add_index "labels", ["project_id"], name: "index_labels_on_project_id", using: :btree
 
create_table "ldap_group_links", force: true do |t|
t.string "cn", null: false
t.integer "group_access", null: false
t.integer "group_id", null: false
t.datetime "created_at"
t.datetime "updated_at"
t.string "provider"
end
create_table "members", force: true do |t|
t.integer "access_level", null: false
t.integer "source_id", null: false
Loading
Loading
@@ -250,8 +217,6 @@ ActiveRecord::Schema.define(version: 20141121161704) do
t.string "type"
t.string "description", default: "", null: false
t.string "avatar"
t.string "ldap_cn"
t.integer "ldap_access"
end
 
add_index "namespaces", ["name"], name: "index_namespaces_on_name", using: :btree
Loading
Loading
@@ -283,14 +248,6 @@ ActiveRecord::Schema.define(version: 20141121161704) do
add_index "notes", ["project_id"], name: "index_notes_on_project_id", using: :btree
add_index "notes", ["updated_at"], name: "index_notes_on_updated_at", using: :btree
 
create_table "project_group_links", force: true do |t|
t.integer "project_id", null: false
t.integer "group_id", null: false
t.datetime "created_at"
t.datetime "updated_at"
t.integer "group_access", default: 30, null: false
end
create_table "projects", force: true do |t|
t.string "name"
t.string "path"
Loading
Loading
@@ -298,22 +255,21 @@ ActiveRecord::Schema.define(version: 20141121161704) do
t.datetime "created_at"
t.datetime "updated_at"
t.integer "creator_id"
t.boolean "issues_enabled", default: true, null: false
t.boolean "wall_enabled", default: true, null: false
t.boolean "merge_requests_enabled", default: true, null: false
t.boolean "wiki_enabled", default: true, null: false
t.boolean "issues_enabled", default: true, null: false
t.boolean "wall_enabled", default: true, null: false
t.boolean "merge_requests_enabled", default: true, null: false
t.boolean "wiki_enabled", default: true, null: false
t.integer "namespace_id"
t.string "issues_tracker", default: "gitlab", null: false
t.string "issues_tracker", default: "gitlab", null: false
t.string "issues_tracker_id"
t.boolean "snippets_enabled", default: true, null: false
t.boolean "snippets_enabled", default: true, null: false
t.datetime "last_activity_at"
t.string "import_url"
t.integer "visibility_level", default: 0, null: false
t.boolean "archived", default: false, null: false
t.integer "visibility_level", default: 0, null: false
t.boolean "archived", default: false, null: false
t.string "import_status"
t.float "repository_size", default: 0.0
t.integer "star_count", default: 0, null: false
t.text "merge_requests_template"
t.float "repository_size", default: 0.0
t.integer "star_count", default: 0, null: false
end
 
add_index "projects", ["creator_id"], name: "index_projects_on_creator_id", using: :btree
Loading
Loading
@@ -379,12 +335,12 @@ ActiveRecord::Schema.define(version: 20141121161704) do
end
 
create_table "users", force: true do |t|
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "reset_password_token"
t.datetime "reset_password_sent_at"
t.datetime "remember_created_at"
t.integer "sign_in_count", default: 0
t.integer "sign_in_count", default: 0
t.datetime "current_sign_in_at"
t.datetime "last_sign_in_at"
t.string "current_sign_in_ip"
Loading
Loading
@@ -392,35 +348,32 @@ ActiveRecord::Schema.define(version: 20141121161704) do
t.datetime "created_at"
t.datetime "updated_at"
t.string "name"
t.boolean "admin", default: false, null: false
t.integer "projects_limit", default: 10
t.string "skype", default: "", null: false
t.string "linkedin", default: "", null: false
t.string "twitter", default: "", null: false
t.boolean "admin", default: false, null: false
t.integer "projects_limit", default: 10
t.string "skype", default: "", null: false
t.string "linkedin", default: "", null: false
t.string "twitter", default: "", null: false
t.string "authentication_token"
t.integer "theme_id", default: 1, null: false
t.integer "theme_id", default: 1, null: false
t.string "bio"
t.integer "failed_attempts", default: 0
t.integer "failed_attempts", default: 0
t.datetime "locked_at"
t.string "extern_uid"
t.string "provider"
t.string "username"
t.boolean "can_create_group", default: true, null: false
t.boolean "can_create_team", default: true, null: false
t.boolean "can_create_group", default: true, null: false
t.boolean "can_create_team", default: true, null: false
t.string "state"
t.integer "color_scheme_id", default: 1, null: false
t.integer "notification_level", default: 1, null: false
t.integer "color_scheme_id", default: 1, null: false
t.integer "notification_level", default: 1, null: false
t.datetime "password_expires_at"
t.integer "created_by_id"
t.datetime "last_credential_check_at"
t.string "avatar"
t.string "confirmation_token"
t.datetime "confirmed_at"
t.datetime "confirmation_sent_at"
t.string "unconfirmed_email"
t.boolean "hide_no_ssh_key", default: false
t.string "website_url", default: "", null: false
t.datetime "last_credential_check_at"
t.datetime "admin_email_unsubscribed_at"
t.boolean "hide_no_ssh_key", default: false
t.string "website_url", default: "", null: false
end
 
add_index "users", ["admin"], name: "index_users_on_admin", using: :btree
Loading
Loading
@@ -428,7 +381,6 @@ ActiveRecord::Schema.define(version: 20141121161704) do
add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree
add_index "users", ["current_sign_in_at"], name: "index_users_on_current_sign_in_at", using: :btree
add_index "users", ["email"], name: "index_users_on_email", unique: true, using: :btree
add_index "users", ["extern_uid", "provider"], name: "index_users_on_extern_uid_and_provider", unique: true, using: :btree
add_index "users", ["name"], name: "index_users_on_name", using: :btree
add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true, using: :btree
add_index "users", ["username"], name: "index_users_on_username", using: :btree
Loading
Loading
Loading
Loading
@@ -170,7 +170,7 @@ class Spinach::Features::Profile < Spinach::FeatureSteps
end
 
step "I am not an ldap user" do
current_user.update_attributes(extern_uid: nil, provider: '')
current_user.identities.delete
current_user.ldap_user?.should be_false
end
 
Loading
Loading
Loading
Loading
@@ -14,10 +14,14 @@ module API
expose :bio, :skype, :linkedin, :twitter, :website_url
end
 
class Identity < Grape::Entity
expose :provider, :extern_uid
end
class UserFull < User
expose :email
expose :theme_id, :color_scheme_id, :extern_uid, :provider, \
:projects_limit
expose :theme_id, :color_scheme_id, :projects_limit
expose :identities, using: Entities::Identity
expose :can_create_group?, as: :can_create_group
expose :can_create_project?, as: :can_create_project
end
Loading
Loading
Loading
Loading
@@ -59,10 +59,16 @@ module API
post do
authenticated_as_admin!
required_attributes! [:email, :password, :name, :username]
attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :extern_uid, :provider, :bio, :can_create_group, :admin]
attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :projects_limit, :username, :bio, :can_create_group, :admin]
user = User.build_user(attrs)
admin = attrs.delete(:admin)
user.admin = admin unless admin.nil?
identity_attrs = attributes_for_keys [:provider, :extern_uid]
if identity_attrs.any?
user.identities.build(identity_attrs)
end
if user.save
present user, with: Entities::UserFull
else
Loading
Loading
@@ -89,8 +95,6 @@ module API
# twitter - Twitter account
# website_url - Website url
# projects_limit - Limit projects each user can create
# extern_uid - External authentication provider UID
# provider - External provider
# bio - Bio
# admin - User is admin - true or false (default)
# can_create_group - User can create groups - true or false
Loading
Loading
@@ -99,7 +103,7 @@ module API
put ":id" do
authenticated_as_admin!
 
attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :website_url, :projects_limit, :username, :extern_uid, :provider, :bio, :can_create_group, :admin]
attrs = attributes_for_keys [:email, :name, :password, :skype, :linkedin, :twitter, :website_url, :projects_limit, :username, :bio, :can_create_group, :admin]
user = User.find(params[:id])
not_found!('User') unless user
 
Loading
Loading
Loading
Loading
@@ -8,7 +8,7 @@ module Gitlab
attr_reader :adapter, :provider, :user
 
def self.open(user, &block)
Gitlab::LDAP::Adapter.open(user.provider) do |adapter|
Gitlab::LDAP::Adapter.open(user.ldap_identity.provider) do |adapter|
block.call(self.new(user, adapter))
end
end
Loading
Loading
@@ -28,13 +28,13 @@ module Gitlab
def initialize(user, adapter=nil)
@adapter = adapter
@user = user
@provider = user.provider
@provider = user.ldap_identity.provider
end
 
def allowed?
if Gitlab::LDAP::Person.find_by_dn(user.extern_uid, adapter)
if Gitlab::LDAP::Person.find_by_dn(user.ldap_identity.extern_uid, adapter)
return true unless ldap_config.active_directory
!Gitlab::LDAP::Person.disabled_via_active_directory?(user.extern_uid, adapter)
!Gitlab::LDAP::Person.disabled_via_active_directory?(user.ldap_identity.extern_uid, adapter)
else
false
end
Loading
Loading
Loading
Loading
@@ -35,15 +35,13 @@ module Gitlab
end
 
def find_by_email
User.find_by(email: auth_hash.email)
::User.find_by(email: auth_hash.email)
end
 
def update_user_attributes
gl_user.attributes = {
extern_uid: auth_hash.uid,
provider: auth_hash.provider,
email: auth_hash.email
}
gl_user.email = auth_hash.email
gl_user.identities.build(provider: auth_hash.provider, extern_uid: auth_hash.uid)
gl_user
end
 
def changed?
Loading
Loading
Loading
Loading
@@ -5,6 +5,8 @@
#
module Gitlab
module OAuth
class ForbiddenAction < StandardError; end
class User
attr_accessor :auth_hash, :gl_user
 
Loading
Loading
@@ -27,9 +29,11 @@ module Gitlab
def save
unauthorized_to_create unless gl_user
 
gl_user.save!
if needs_blocking?
gl_user.save!
gl_user.block
else
gl_user.save!
end
 
log.info "(OAuth) saving user #{auth_hash.email} from login with extern_uid => #{auth_hash.uid}"
Loading
Loading
@@ -73,9 +77,10 @@ module Gitlab
end
 
def build_new_user
user = User.new(user_attributes)
user = ::User.new(user_attributes)
user.skip_confirmation!
user.identities.new(extern_uid: auth_hash.uid, provider: auth_hash.provider)
user
end
 
def user_attributes
Loading
Loading
@@ -92,8 +97,8 @@ module Gitlab
Gitlab::AppLogger
end
 
def raise_unauthorized_to_create
raise StandardError.new("Unauthorized to create user, signup disabled for #{auth_hash.provider}")
def unauthorized_to_create
raise ForbiddenAction.new("Unauthorized to create user, signup disabled for #{auth_hash.provider}")
end
end
end
Loading
Loading
Loading
Loading
@@ -18,15 +18,24 @@ FactoryGirl.define do
password "12345678"
password_confirmation { password }
confirmed_at { Time.now }
confirmation_token { nil }
confirmation_token { nil }
 
trait :admin do
admin true
end
 
trait :ldap do
provider 'ldapmain'
extern_uid 'my-ldap-id'
factory :omniauth_user do
ignore do
extern_uid '123456'
provider 'ldapmain'
end
after(:create) do |user, evaluator|
user.identities << create(:identity,
provider: evaluator.provider,
extern_uid: evaluator.extern_uid
)
end
end
 
factory :admin, traits: [:admin]
Loading
Loading
@@ -182,4 +191,9 @@ FactoryGirl.define do
deploy_key
project
end
factory :identity do
provider 'ldapmain'
extern_uid 'my-ldap-id'
end
end
Loading
Loading
@@ -15,18 +15,18 @@ describe Gitlab::LDAP::User do
 
describe :find_or_create do
it "finds the user if already existing" do
existing_user = create(:user, extern_uid: 'my-uid', provider: 'ldapmain')
existing_user = create(:omniauth_user, extern_uid: 'my-uid', provider: 'ldapmain')
 
expect{ gl_user.save }.to_not change{ User.count }
end
 
it "connects to existing non-ldap user if the email matches" do
existing_user = create(:user, email: 'john@example.com')
existing_user = create(:omniauth_user, email: 'john@example.com')
expect{ gl_user.save }.to_not change{ User.count }
 
existing_user.reload
expect(existing_user.extern_uid).to eql 'my-uid'
expect(existing_user.provider).to eql 'ldapmain'
expect(existing_user.ldap_identity.extern_uid).to eql 'my-uid'
expect(existing_user.ldap_identity.provider).to eql 'ldapmain'
end
 
it "creates a new user if not found" do
Loading
Loading
Loading
Loading
@@ -15,7 +15,7 @@ describe Gitlab::OAuth::User do
end
 
describe :persisted? do
let!(:existing_user) { create(:user, extern_uid: 'my-uid', provider: 'my-provider') }
let!(:existing_user) { create(:omniauth_user, extern_uid: 'my-uid', provider: 'my-provider') }
 
it "finds an existing user based on uid and provider (facebook)" do
auth = double(info: double(name: 'John'), uid: 'my-uid', provider: 'my-provider')
Loading
Loading
@@ -39,8 +39,9 @@ describe Gitlab::OAuth::User do
oauth_user.save
 
expect(gl_user).to be_valid
expect(gl_user.extern_uid).to eql uid
expect(gl_user.provider).to eql 'twitter'
identity = gl_user.identities.first
expect(identity.extern_uid).to eql uid
expect(identity.provider).to eql 'twitter'
end
end
 
Loading
Loading
Loading
Loading
@@ -62,6 +62,7 @@ describe User do
it { should have_many(:assigned_issues).dependent(:destroy) }
it { should have_many(:merge_requests).dependent(:destroy) }
it { should have_many(:assigned_merge_requests).dependent(:destroy) }
it { should have_many(:identities).dependent(:destroy) }
end
 
describe "Mass assignment" do
Loading
Loading
@@ -361,24 +362,29 @@ describe User do
end
 
describe :ldap_user? do
let(:user) { build(:user, :ldap) }
it "is true if provider name starts with ldap" do
user.provider = 'ldapmain'
user = create(:omniauth_user, provider: 'ldapmain')
expect( user.ldap_user? ).to be_true
end
 
it "is false for other providers" do
user.provider = 'other-provider'
user = create(:omniauth_user, provider: 'other-provider')
expect( user.ldap_user? ).to be_false
end
 
it "is false if no extern_uid is provided" do
user.extern_uid = nil
user = create(:omniauth_user, extern_uid: nil)
expect( user.ldap_user? ).to be_false
end
end
 
describe :ldap_identity do
it "returns ldap identity" do
user = create :omniauth_user
user.ldap_identity.provider.should_not be_empty
end
end
describe '#full_website_url' do
let(:user) { create(:user) }
 
Loading
Loading
Loading
Loading
@@ -33,7 +33,7 @@ describe API::API, api: true do
response.status.should == 200
json_response.should be_an Array
json_response.first.keys.should include 'email'
json_response.first.keys.should include 'extern_uid'
json_response.first.keys.should include 'identities'
json_response.first.keys.should include 'can_create_project'
end
end
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment