207 lines
7 KiB
Diff
207 lines
7 KiB
Diff
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
|
|
index 59a4d1f..e48dfe7 100644
|
|
--- a/config/gitlab.yml.example
|
|
+++ b/config/gitlab.yml.example
|
|
@@ -103,6 +103,10 @@ production: &base
|
|
bind_dn: '_the_full_dn_of_the_user_you_will_bind_with'
|
|
password: '_the_password_of_the_bind_user'
|
|
allow_username_or_email_login: true
|
|
+ mapping:
|
|
+ name: 'cn'
|
|
+ username: 'uid'
|
|
+ email: 'mail'
|
|
|
|
## OmniAuth settings
|
|
omniauth:
|
|
@@ -131,7 +135,14 @@ production: &base
|
|
# - { name: 'github', app_id: 'YOUR APP ID',
|
|
# app_secret: 'YOUR APP SECRET' }
|
|
|
|
-
|
|
+ ## User Mapping Procs
|
|
+ # These procs allow for custom mapping of user information from LDAP / Omniauth
|
|
+ # onto your user model.
|
|
+ #
|
|
+ # user_mapping:
|
|
+ # name: ->(auth) { auth.info.name.to_s }
|
|
+ # username: ->(auth) { auth.info.email.to_s.downcase.match(/^[^@]*/)[0] }
|
|
+ # email: ->(auth) { auth.info.email.to_s.downcase }
|
|
|
|
#
|
|
# 3. Advanced settings
|
|
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
|
|
index e0207c6..c079cc4 100644
|
|
--- a/config/initializers/1_settings.rb
|
|
+++ b/config/initializers/1_settings.rb
|
|
@@ -36,6 +36,7 @@ end
|
|
|
|
# Default settings
|
|
Settings['ldap'] ||= Settingslogic.new({})
|
|
+Settings.ldap['mapping'] ||= Settingslogic.new({})
|
|
Settings.ldap['enabled'] = false if Settings.ldap['enabled'].nil?
|
|
Settings.ldap['allow_username_or_email_login'] = false if Settings.ldap['allow_username_or_email_login'].nil?
|
|
|
|
diff --git a/lib/gitlab/auth.rb b/lib/gitlab/auth.rb
|
|
index de70c5c..bea8191 100644
|
|
--- a/lib/gitlab/auth.rb
|
|
+++ b/lib/gitlab/auth.rb
|
|
@@ -33,13 +33,14 @@ module Gitlab
|
|
def create_from_omniauth(auth, ldap = false)
|
|
provider = auth.provider
|
|
uid = auth.info.uid || auth.uid
|
|
- uid = uid.to_s.force_encoding("utf-8")
|
|
- name = auth.info.name.to_s.force_encoding("utf-8")
|
|
- email = auth.info.email.to_s.downcase unless auth.info.email.nil?
|
|
+ uid = uid.to_s.force_encoding('utf-8')
|
|
+ name = extract(:name, auth, ldap).force_encoding('utf-8')
|
|
+ username = extract(:username, auth, ldap).force_encoding('utf-8')
|
|
+ email = extract(:email, auth, ldap).force_encoding('utf-8')
|
|
|
|
ldap_prefix = ldap ? '(LDAP) ' : ''
|
|
raise OmniAuth::Error, "#{ldap_prefix}#{provider} does not provide an email"\
|
|
- " address" if auth.info.email.blank?
|
|
+ " address" if email.blank?
|
|
|
|
log.info "#{ldap_prefix}Creating user from #{provider} login"\
|
|
" {uid => #{uid}, name => #{name}, email => #{email}}"
|
|
@@ -48,7 +49,7 @@ module Gitlab
|
|
extern_uid: uid,
|
|
provider: provider,
|
|
name: name,
|
|
- username: email.match(/^[^@]*/)[0],
|
|
+ username: username,
|
|
email: email,
|
|
password: password,
|
|
password_confirmation: password,
|
|
@@ -101,5 +102,31 @@ module Gitlab
|
|
def ldap_conf
|
|
@ldap_conf ||= Gitlab.config.ldap
|
|
end
|
|
+
|
|
+ private
|
|
+
|
|
+ def extract(field_name, auth, ldap = false)
|
|
+ @ldap_mapper ||= Gitlab.config.ldap.mapping rescue Hash.new
|
|
+ @mapper ||= begin
|
|
+ defaults = {
|
|
+ name: ->(auth) { auth.info.name.to_s },
|
|
+ username: ->(auth) { auth.info.email.to_s.downcase.match(/^[^@]*/)[0] },
|
|
+ email: ->(auth) { auth.info.email.to_s.downcase },
|
|
+ }
|
|
+ extras = Gitlab.config.user_mapping rescue Hash.new
|
|
+ defaults.merge(extras)
|
|
+ end
|
|
+
|
|
+ if ldap && !@ldap_mapper[field_name].nil?
|
|
+ begin
|
|
+ ldap_attr = @ldap_mapper[field_name].to_sym
|
|
+ Array(auth.extra.raw_info[ldap_attr])[0]
|
|
+ rescue
|
|
+ raise "(LDAP) Failed to get '#{@ldap_mapper[field_name]}' for #{field_name} for #{auth.info.uid}"
|
|
+ end
|
|
+ else
|
|
+ @mapper[field_name].call(auth)
|
|
+ end
|
|
+ end
|
|
end
|
|
end
|
|
diff --git a/spec/lib/auth_spec.rb b/spec/lib/auth_spec.rb
|
|
index 903d276..cf9e7b7 100644
|
|
--- a/spec/lib/auth_spec.rb
|
|
+++ b/spec/lib/auth_spec.rb
|
|
@@ -4,7 +4,7 @@ describe Gitlab::Auth do
|
|
let(:gl_auth) { Gitlab::Auth.new }
|
|
|
|
before do
|
|
- Gitlab.config.stub(omniauth: {})
|
|
+ Gitlab.config.stub(omniauth: {}, ldap: {})
|
|
|
|
@info = mock(
|
|
uid: '12djsak321',
|
|
@@ -74,9 +74,22 @@ describe Gitlab::Auth do
|
|
end
|
|
|
|
describe :create_from_omniauth do
|
|
+ before do
|
|
+ @raw_info = {
|
|
+ cn: 'John Black',
|
|
+ mail: [ 'john.black@email.com' ],
|
|
+ nickname: 'jonny'
|
|
+ }
|
|
+
|
|
+ @ldap_auth = mock(
|
|
+ info: @info,
|
|
+ extra: mock(raw_info: @raw_info),
|
|
+ provider: 'ldap'
|
|
+ )
|
|
+ end
|
|
+
|
|
it "should create user from LDAP" do
|
|
- @auth = mock(info: @info, provider: 'ldap')
|
|
- user = gl_auth.create_from_omniauth(@auth, true)
|
|
+ user = gl_auth.create_from_omniauth(@ldap_auth, true)
|
|
|
|
user.should be_valid
|
|
user.extern_uid.should == @info.uid
|
|
@@ -92,9 +105,59 @@ describe Gitlab::Auth do
|
|
user.provider.should == 'twitter'
|
|
end
|
|
|
|
+ it "should still import without extra mapping" do
|
|
+ Gitlab.config.stub(omniauth: {})
|
|
+ user = gl_auth.create_from_omniauth(@ldap_auth, true)
|
|
+
|
|
+ user.should be_valid
|
|
+ user.extern_uid.should == @info.uid
|
|
+ user.provider.should == 'ldap'
|
|
+ end
|
|
+
|
|
+ it "should have user details from procs" do
|
|
+ Gitlab.config.stub(omniauth: {}, user_mapping: {})
|
|
+ Gitlab.config.user_mapping[:name] = ->(auth) { 'TestName' }
|
|
+ Gitlab.config.user_mapping[:email] = ->(auth) { 'email@somewhere.com' }
|
|
+ Gitlab.config.user_mapping[:username] = ->(auth) { 'TestUsername' }
|
|
+
|
|
+ user = gl_auth.create_from_omniauth(@ldap_auth, true)
|
|
+ user.should be_valid
|
|
+ user.extern_uid.should == @info.uid
|
|
+ user.name.should == 'TestName'
|
|
+ user.email.should == 'email@somewhere.com'
|
|
+ user.username.should == 'TestUsername'
|
|
+ end
|
|
+
|
|
+ it "should modify value using proc" do
|
|
+ Gitlab.config.stub(omniauth: {}, user_mapping: {})
|
|
+ Gitlab.config.user_mapping[:username] = ->(auth) { auth.info.email.to_s.downcase.split('@').first }
|
|
+
|
|
+ user = gl_auth.create_from_omniauth(@ldap_auth, true)
|
|
+ user.should be_valid
|
|
+ user.extern_uid.should == @info.uid
|
|
+ user.username.should == 'john'
|
|
+ end
|
|
+
|
|
+ it "should be able to use raw ldap information through simple ldap mapping" do
|
|
+ Gitlab.config.ldap.stub(mapping: { name: 'cn', email: 'mail' })
|
|
+
|
|
+ user = gl_auth.create_from_omniauth(@ldap_auth, true)
|
|
+ user.should be_valid
|
|
+ user.extern_uid.should == @info.uid
|
|
+ user.name.should == 'John Black'
|
|
+ user.email.should == 'john.black@email.com'
|
|
+ end
|
|
+
|
|
+ it "should raise an error if an invalid field is in ldap mapping" do
|
|
+ Gitlab.config.ldap.stub(mapping: { name: 'invalid' })
|
|
+
|
|
+ expect {
|
|
+ gl_auth.create_from_omniauth(@ldap_auth, true)
|
|
+ }.to raise_error
|
|
+ end
|
|
+
|
|
it "should apply defaults to user" do
|
|
- @auth = mock(info: @info, provider: 'ldap')
|
|
- user = gl_auth.create_from_omniauth(@auth, true)
|
|
+ user = gl_auth.create_from_omniauth(@ldap_auth, true)
|
|
|
|
user.should be_valid
|
|
user.projects_limit.should == Gitlab.config.gitlab.default_projects_limit
|