gentoo-overlay/www-apps/gitlabhq/files/gitlabhq-6.0.2-ldap-user-ma...

208 lines
7.0 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