user.rb 2.96 KB
Newer Older
1 2
require 'gitlab/oauth/user'

3 4 5 6
# LDAP extension for User model
#
# * Find or create user from omniauth.auth data
# * Links LDAP account with existing user
7
# * Auth LDAP user with login and password
8 9 10
#
module Gitlab
  module LDAP
11
    class User < Gitlab::OAuth::User
12 13
      class << self
        def find_or_create(auth)
14
          @auth = auth
15 16 17 18 19

          if uid.blank? || email.blank?
            raise_error("Account must provide an uid and email address")
          end

20 21 22 23 24 25 26 27 28
          user = find(auth)

          unless user
            # Look for user with same emails
            #
            # Possible cases:
            # * When user already has account and need to link his LDAP account.
            # * LDAP uid changed for user with same email and we need to update his uid
            #
29
            user = find_user(email)
30 31 32 33 34 35 36 37 38 39 40 41

            if user
              user.update_attributes(extern_uid: uid, provider: provider)
              log.info("(LDAP) Updating legacy LDAP user #{email} with extern_uid => #{uid}")
            else
              # Create a new user inside GitLab database
              # based on LDAP credentials
              #
              #
              user = create(auth)
            end
          end
42

43
          user
44 45
        end

46
        def find_user(email)
Izaak Alpert's avatar
Izaak Alpert committed
47 48 49 50 51 52
          user = model.find_by_email(email)

          # If no user found and allow_username_or_email_login is true
          # we look for user by extracting part of his email
          if !user && email && ldap_conf['allow_username_or_email_login']
            uname = email.partition('@').first
53 54
            user = model.find_by_username(uname)
          end
Izaak Alpert's avatar
Izaak Alpert committed
55

56 57 58
          user
        end

59
        def authenticate(login, password)
60 61 62 63 64 65 66 67 68 69 70 71 72 73
          # Check user against LDAP backend if user is not authenticated
          # Only check with valid login and password to prevent anonymous bind results
          return nil unless ldap_conf.enabled && login.present? && password.present?

          ldap = OmniAuth::LDAP::Adaptor.new(ldap_conf)
          ldap_user = ldap.bind_as(
            filter: Net::LDAP::Filter.eq(ldap.uid, login),
            size: 1,
            password: password
          )

          find_by_uid(ldap_user.dn) if ldap_user
        end

74 75 76 77 78 79 80
        # Check LDAP user existance by dn. User in git over ssh check
        #
        # It covers 2 cases:
        # * when ldap account was removed
        # * when ldap account was deactivated by change of OU membership in 'dn'
        def blocked?(dn)
          ldap = OmniAuth::LDAP::Adaptor.new(ldap_conf)
81
          ldap.connection.search(base: dn, scope: Net::LDAP::SearchScope_BaseObject, size: 1).blank?
82 83
        end

84 85
        private

86 87
        def find_by_uid(uid)
          model.where(provider: provider, extern_uid: uid).last
88 89
        end

90 91
        def provider
          'ldap'
92 93 94 95 96 97
        end

        def raise_error(message)
          raise OmniAuth::Error, "(LDAP) " + message
        end

98 99 100
        def ldap_conf
          Gitlab.config.ldap
        end
101 102 103 104
      end
    end
  end
end