Changeset - e80b2cbbd4ba
[Not reviewed]
Merge beta
0 12 0
Marcin Kuzminski - 15 years ago 2011-02-04 12:29:45
marcin@python-works.com
merge thayne ldap extensions
12 files changed with 324 insertions and 77 deletions:
0 comments (0 inline, 0 general)
docs/setup.rst
Show inline comments
 
@@ -124,13 +124,13 @@ the `-f` flag passed to paster command o
 

	
 

	
 
Setting up LDAP support
 
-----------------------
 

	
 
RhodeCode starting from version 1.1 supports ldap authentication. In order
 
to use ldap, You have to install python-ldap package. This package is available
 
to use LDAP, You have to install python-ldap_ package. This package is available
 
via pypi, so You can install it by running
 

	
 
::
 

	
 
 easy_install python-ldap
 
 
 
@@ -139,45 +139,187 @@ via pypi, so You can install it by runni
 
 pip install python-ldap
 

	
 
.. note::
 
   python-ldap requires some certain libs on Your system, so before installing 
 
   it check that You have at least `openldap`, and `sasl` libraries.
 

	
 
ldap settings are located in admin->ldap section,
 
LDAP settings are located in admin->ldap section,
 

	
 
This is a typical LDAP setup::
 

	
 
 Connection settings
 
 Enable LDAP          = checked
 
 Host                 = host.example.org
 
 Port                 = 389
 
 Account              = <account>
 
 Password             = <password>
 
 Enable LDAPS         = checked
 
 Certificate Checks   = DEMAND
 

	
 
 Search settings
 
 Base DN              = CN=users,DC=host,DC=example,DC=org
 
 LDAP Filter          = (&(objectClass=user)(!(objectClass=computer)))
 
 LDAP Search Scope    = SUBTREE
 

	
 
Here's a typical ldap setup::
 
 Attribute mappings
 
 Login Attribute      = uid
 
 First Name Attribute = firstName
 
 Last Name Attribute  = lastName
 
 E-mail Attribute     = mail
 

	
 
.. _enable_ldap:
 

	
 
Enable LDAP : required
 
    Whether to use LDAP for authenticating users.
 

	
 
.. _ldap_host:
 

	
 
Host : required
 
    LDAP server hostname or IP address.
 

	
 
.. _Port:
 

	
 
Port : required
 
    389 for un-encrypted LDAP, 636 for SSL-encrypted LDAP.
 

	
 
.. _ldap_account:
 

	
 
 Enable ldap  = checked                 #controls if ldap access is enabled
 
 Host         = host.domain.org         #actual ldap server to connect
 
 Port         = 389 or 689 for ldaps    #ldap server ports
 
 Enable LDAPS = unchecked               #enable disable ldaps
 
 Account      = <account>               #access for ldap server(if required)
 
 Password     = <password>              #password for ldap server(if required)
 
 Base DN      = uid=%(user)s,CN=users,DC=host,DC=domain,DC=org
 
 
 
Account : optional
 
    Only required if the LDAP server does not allow anonymous browsing of
 
    records.  This should be a special account for record browsing.  This
 
    will require `LDAP Password`_ below.
 

	
 
.. _LDAP Password:
 

	
 
Password : optional
 
    Only required if the LDAP server does not allow anonymous browsing of
 
    records.
 

	
 
.. _Enable LDAPS:
 

	
 
Enable LDAPS : optional
 
    Check this if SSL encryption is necessary for communication with the
 
    LDAP server - it will likely require `Port`_ to be set to a different
 
    value (standard LDAPS port is 636).  When LDAPS is enabled then
 
    `Certificate Checks`_ is required.
 

	
 
.. _Certificate Checks:
 

	
 
`Account` and `Password` are optional, and used for two-phase ldap 
 
authentication so those are credentials to access Your ldap, if it doesn't 
 
support anonymous search/user lookups. 
 
Certificate Checks : optional
 
    How SSL certificates verification is handled - this is only useful when
 
    `Enable LDAPS`_ is enabled.  Only DEMAND or HARD offer full SSL security while
 
    the other options are susceptible to man-in-the-middle attacks.  SSL
 
    certificates can be installed to /etc/openldap/cacerts so that the
 
    DEMAND or HARD options can be used with self-signed certificates or
 
    certificates that do not have traceable certificates of authority.
 

	
 
    NEVER
 
        A serve certificate will never be requested or checked.
 

	
 
    ALLOW
 
        A server certificate is requested.  Failure to provide a
 
        certificate or providing a bad certificate will not terminate the
 
        session.
 

	
 
    TRY
 
        A server certificate is requested.  Failure to provide a
 
        certificate does not halt the session; providing a bad certificate
 
        halts the session.
 

	
 
    DEMAND
 
        A server certificate is requested and must be provided and
 
        authenticated for the session to proceed.
 

	
 
Base DN must have %(user)s template inside, it's a placer where Your uid used
 
to login would go, it allows admins to specify not standard schema for uid 
 
variable
 
    HARD
 
        The same as DEMAND.
 

	
 
.. _Base DN:
 

	
 
Base DN : required
 
    The Distinguished Name (DN) where searches for users will be performed.
 
    Searches can be controlled by `LDAP Filter`_ and `LDAP Search Scope`_.
 

	
 
.. _LDAP Filter:
 

	
 
LDAP Filter : optional
 
    A LDAP filter defined by RFC 2254.  This is more useful when `LDAP
 
    Search Scope`_ is set to SUBTREE.  The filter is useful for limiting
 
    which LDAP objects are identified as representing Users for
 
    authentication.  The filter is augmented by `Login Attribute`_ below.
 
    This can commonly be left blank.
 

	
 
.. _LDAP Search Scope:
 

	
 
LDAP Search Scope : required
 
    This limits how far LDAP will search for a matching object.
 

	
 
    BASE
 
        Only allows searching of `Base DN`_ and is usually not what you
 
        want.
 

	
 
    ONELEVEL
 
        Searches all entries under `Base DN`_, but not Base DN itself.
 

	
 
    SUBTREE
 
        Searches all entries below `Base DN`_, but not Base DN itself.
 
        When using SUBTREE `LDAP Filter`_ is useful to limit object
 
        location.
 

	
 
.. _Login Attribute:
 

	
 
If all data are entered correctly, and `python-ldap` is properly installed
 
Users should be granted to access RhodeCode wit ldap accounts. When 
 
logging at the first time an special ldap account is created inside RhodeCode, 
 
so You can control over permissions even on ldap users. If such user exists 
 
already in RhodeCode database ldap user with the same username would be not 
 
able to access RhodeCode.
 
Login Attribute : required        
 
    The LDAP record attribute that will be matched as the USERNAME or
 
    ACCOUNT used to connect to RhodeCode.  This will be added to `LDAP
 
    Filter`_ for locating the User object.  If `LDAP Filter`_ is specified as
 
    "LDAPFILTER", `Login Attribute`_ is specified as "uid" and the user has
 
    connected as "jsmith" then the `LDAP Filter`_ will be augmented as below
 
    ::
 

	
 
        (&(LDAPFILTER)(uid=jsmith))
 

	
 
.. _ldap_attr_firstname:
 

	
 
First Name Attribute : required
 
    The LDAP record attribute which represents the user's first name.
 

	
 
.. _ldap_attr_lastname:
 

	
 
Last Name Attribute : required
 
    The LDAP record attribute which represents the user's last name.
 

	
 
.. _ldap_attr_email:
 

	
 
Email Attribute : required
 
    The LDAP record attribute which represents the user's email address.
 

	
 
If You have problems with ldap access and believe You entered correct 
 
information check out the RhodeCode logs,any error messages sent from 
 
ldap will be saved there.
 
If all data are entered correctly, and python-ldap_ is properly installed
 
users should be granted access to RhodeCode with ldap accounts.  At this
 
time user information is copied from LDAP into the RhodeCode user database.
 
This means that updates of an LDAP user object may not be reflected as a
 
user update in RhodeCode.
 

	
 
If You have problems with LDAP access and believe You entered correct
 
information check out the RhodeCode logs, any error messages sent from LDAP
 
will be saved there.
 

	
 
Active Directory
 
''''''''''''''''
 

	
 
RhodeCode can use Microsoft Active Directory for user authentication.  This
 
is done through an LDAP or LDAPS connection to Active Directory.  The
 
following LDAP configuration settings are typical for using Active
 
Directory ::
 

	
 
 Base DN              = OU=SBSUsers,OU=Users,OU=MyBusiness,DC=v3sys,DC=local
 
 Login Attribute      = sAMAccountName
 
 First Name Attribute = givenName
 
 Last Name Attribute  = sn
 
 E-mail Attribute     = mail
 

	
 
All other LDAP settings will likely be site-specific and should be
 
appropriately configured.
 

	
 
Setting Up Celery
 
-----------------
 

	
 
Since version 1.1 celery is configured by the rhodecode ini configuration files
 
simply set use_celery=true in the ini file then add / change the configuration 
 
@@ -323,7 +465,8 @@ Troubleshooting
 

	
 

	
 
.. _virtualenv: http://pypi.python.org/pypi/virtualenv
 
.. _python: http://www.python.org/
 
.. _mercurial: http://mercurial.selenic.com/
 
.. _celery: http://celeryproject.org/
 
.. _rabbitmq: http://www.rabbitmq.com/
 
\ No newline at end of file
 
.. _rabbitmq: http://www.rabbitmq.com/
 
.. _python-ldap: http://www.python-ldap.org/
rhodecode/controllers/admin/ldap_settings.py
Show inline comments
 
@@ -45,33 +45,52 @@ from sqlalchemy.exc import DatabaseError
 
log = logging.getLogger(__name__)
 

	
 

	
 

	
 
class LdapSettingsController(BaseController):
 

	
 
    search_scope_choices = [('BASE',     _('BASE'),),
 
                            ('ONELEVEL', _('ONELEVEL'),),
 
                            ('SUBTREE',  _('SUBTREE'),),
 
                            ]
 
    search_scope_default = 'SUBTREE'
 

	
 
    tls_reqcert_choices = [('NEVER',  _('NEVER'),),
 
                           ('ALLOW',  _('ALLOW'),),
 
                           ('TRY',    _('TRY'),),
 
                           ('DEMAND', _('DEMAND'),),
 
                           ('HARD',   _('HARD'),),
 
                           ]
 
    tls_reqcert_default = 'DEMAND'
 

	
 
    @LoginRequired()
 
    @HasPermissionAllDecorator('hg.admin')
 
    def __before__(self):
 
        c.admin_user = session.get('admin_user')
 
        c.admin_username = session.get('admin_username')
 
        c.search_scope_choices = self.search_scope_choices
 
        c.tls_reqcert_choices  = self.tls_reqcert_choices
 
        super(LdapSettingsController, self).__before__()
 

	
 
    def index(self):
 
        defaults = SettingsModel().get_ldap_settings()
 
        c.search_scope_cur = defaults.get('ldap_search_scope')
 
        c.tls_reqcert_cur  = defaults.get('ldap_tls_reqcert')
 

	
 
        return htmlfill.render(
 
                    render('admin/ldap/ldap.html'),
 
                    defaults=defaults,
 
                    encoding="UTF-8",
 
                    force_defaults=True,)
 

	
 
    def ldap_settings(self):
 
        """POST ldap create and store ldap settings"""
 

	
 
        settings_model = SettingsModel()
 
        _form = LdapSettingsForm()()
 
        _form = LdapSettingsForm([x[0] for x in self.tls_reqcert_choices],
 
                                 [x[0] for x in self.search_scope_choices])()
 

	
 
        try:
 
            form_result = _form.to_python(dict(request.POST))
 
            try:
 

	
 
                for k, v in form_result.items():
 
@@ -88,12 +107,15 @@ class LdapSettingsController(BaseControl
 
        except LdapImportError:
 
            h.flash(_('Unable to activate ldap. The "python-ldap" library '
 
                      'is missing.'), category='warning')
 

	
 
        except formencode.Invalid, errors:
 

	
 
            c.search_scope_cur = self.search_scope_default
 
            c.tls_reqcert_cur  = self.search_scope_default
 

	
 
            return htmlfill.render(
 
                render('admin/ldap/ldap.html'),
 
                defaults=errors.value,
 
                errors=errors.error_dict or {},
 
                prefix_error=False,
 
                encoding="UTF-8")
rhodecode/lib/auth.py
Show inline comments
 
@@ -100,13 +100,13 @@ def authenticate(username, password):
 
    :param password: password
 
    """
 
    user_model = UserModel()
 
    user = user_model.get_by_username(username, cache=False)
 

	
 
    log.debug('Authenticating user using RhodeCode account')
 
    if user is not None and user.is_ldap is False:
 
    if user is not None and not user.ldap_dn:
 
        if user.active:
 

	
 
            if user.username == 'default' and user.active:
 
                log.info('user %s authenticated correctly as anonymous user',
 
                         username)
 
                return True
 
@@ -119,13 +119,13 @@ def authenticate(username, password):
 

	
 
    else:
 
        log.debug('Regular authentication failed')
 
        user_obj = user_model.get_by_username(username, cache=False,
 
                                            case_insensitive=True)
 

	
 
        if user_obj is not None and user_obj.is_ldap is False:
 
        if user_obj is not None and not user_obj.ldap_dn:
 
            log.debug('this user already exists as non ldap')
 
            return False
 

	
 
        from rhodecode.model.settings import SettingsModel
 
        ldap_settings = SettingsModel().get_ldap_settings()
 

	
 
@@ -138,21 +138,31 @@ def authenticate(username, password):
 
                  'server':ldap_settings.get('ldap_host', ''),
 
                  'base_dn':ldap_settings.get('ldap_base_dn', ''),
 
                  'port':ldap_settings.get('ldap_port'),
 
                  'bind_dn':ldap_settings.get('ldap_dn_user'),
 
                  'bind_pass':ldap_settings.get('ldap_dn_pass'),
 
                  'use_ldaps':ldap_settings.get('ldap_ldaps'),
 
                  'tls_reqcert':ldap_settings.get('ldap_tls_reqcert'),
 
                  'ldap_filter':ldap_settings.get('ldap_filter'),
 
                  'search_scope':ldap_settings.get('ldap_search_scope'),
 
                  'attr_login':ldap_settings.get('ldap_attr_login'),
 
                  'ldap_version':3,
 
                  }
 
            log.debug('Checking for ldap authentication')
 
            try:
 
                aldap = AuthLdap(**kwargs)
 
                res = aldap.authenticate_ldap(username, password)
 
                log.debug('Got ldap response %s', res)
 
                (user_dn, ldap_attrs) = aldap.authenticate_ldap(username, password)
 
                log.debug('Got ldap DN response %s', user_dn)
 

	
 
                if user_model.create_ldap(username, password):
 
                user_attrs = {
 
                    'name'     : ldap_attrs[ldap_settings.get('ldap_attr_firstname')][0],
 
                    'lastname' : ldap_attrs[ldap_settings.get('ldap_attr_lastname')][0],
 
                    'email'    : ldap_attrs[ldap_settings.get('ldap_attr_email')][0],
 
                    }
 

	
 
                if user_model.create_ldap(username, password, user_dn, user_attrs):
 
                    log.info('created new ldap user')
 

	
 
                return True
 
            except (LdapUsernameError, LdapPasswordError,):
 
                pass
 
            except (Exception,):
rhodecode/lib/auth_ldap.py
Show inline comments
 
@@ -33,17 +33,21 @@ try:
 
except ImportError:
 
    pass
 

	
 
class AuthLdap(object):
 

	
 
    def __init__(self, server, base_dn, port=389, bind_dn='', bind_pass='',
 
                 use_ldaps=False, ldap_version=3):
 
                 use_ldaps=False, tls_reqcert='DEMAND', ldap_version=3,
 
                 ldap_filter='(&(objectClass=user)(!(objectClass=computer)))',
 
                 search_scope='SUBTREE',
 
                 attr_login='uid'):
 
        self.ldap_version = ldap_version
 
        if use_ldaps:
 
            port = port or 689
 
        self.LDAP_USE_LDAPS = use_ldaps
 
        self.TLS_REQCERT = ldap.__dict__['OPT_X_TLS_' + tls_reqcert]
 
        self.LDAP_SERVER_ADDRESS = server
 
        self.LDAP_SERVER_PORT = port
 

	
 
        #USE FOR READ ONLY BIND TO LDAP SERVER
 
        self.LDAP_BIND_DN = bind_dn
 
        self.LDAP_BIND_PASS = bind_pass
 
@@ -52,12 +56,16 @@ class AuthLdap(object):
 
        if self.LDAP_USE_LDAPS:ldap_server_type = ldap_server_type + 's'
 
        self.LDAP_SERVER = "%s://%s:%s" % (ldap_server_type,
 
                                               self.LDAP_SERVER_ADDRESS,
 
                                               self.LDAP_SERVER_PORT)
 

	
 
        self.BASE_DN = base_dn
 
        self.LDAP_FILTER = ldap_filter
 
        self.SEARCH_SCOPE = ldap.__dict__['SCOPE_' + search_scope]
 
        self.attr_login = attr_login
 

	
 

	
 
    def authenticate_ldap(self, username, password):
 
        """Authenticate a user via LDAP and return his/her LDAP properties.
 
    
 
        Raises AuthenticationError if the credentials are rejected, or
 
        EnvironmentError if the LDAP server can't be reached.
 
@@ -71,34 +79,48 @@ class AuthLdap(object):
 
        uid = chop_at(username, "@%s" % self.LDAP_SERVER_ADDRESS)
 

	
 
        if "," in username:
 
            raise LdapUsernameError("invalid character in username: ,")
 
        try:
 
            ldap.set_option(ldap.OPT_X_TLS_CACERTDIR, '/etc/openldap/cacerts')
 
            ldap.set_option(ldap.OPT_REFERRALS, ldap.OPT_OFF)
 
            ldap.set_option(ldap.OPT_RESTART, ldap.OPT_ON)
 
            ldap.set_option(ldap.OPT_TIMEOUT, 20)
 
            ldap.set_option(ldap.OPT_NETWORK_TIMEOUT, 10)
 
            ldap.set_option(ldap.OPT_TIMELIMIT, 15)
 
            if self.LDAP_USE_LDAPS:
 
                ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, self.TLS_REQCERT)
 
            server = ldap.initialize(self.LDAP_SERVER)
 
            if self.ldap_version == 2:
 
                server.protocol = ldap.VERSION2
 
            else:
 
                server.protocol = ldap.VERSION3
 

	
 
            if self.LDAP_BIND_DN and self.LDAP_BIND_PASS:
 
                server.simple_bind_s(self.LDAP_BIND_DN, self.LDAP_BIND_PASS)
 

	
 
            dn = self.BASE_DN % {'user':uid}
 
            log.debug("Authenticating %r at %s", dn, self.LDAP_SERVER)
 
            server.simple_bind_s(dn, password)
 
            filt = '(&%s(%s=%s))' % (self.LDAP_FILTER, self.attr_login, username)
 
            log.debug("Authenticating %r filt %s at %s", self.BASE_DN, filt, self.LDAP_SERVER)
 
            lobjects = server.search_ext_s(self.BASE_DN, self.SEARCH_SCOPE, filt)
 

	
 
            if not lobjects:
 
                raise ldap.NO_SUCH_OBJECT()
 

	
 
            properties = server.search_s(dn, ldap.SCOPE_SUBTREE)
 
            if not properties:
 
                raise ldap.NO_SUCH_OBJECT()
 
            for (dn, attrs) in lobjects:
 
                try:
 
                    server.simple_bind_s(dn, password)
 
                    break
 

	
 
                except ldap.INVALID_CREDENTIALS, e:
 
                    log.debug("LDAP rejected password for user '%s' (%s): %s", uid, username, dn)
 

	
 
                else:
 
                    log.debug("No matching LDAP objecs for authentication of '%s' (%s)", uid, username)
 
                    raise LdapPasswordError()
 

	
 
        except ldap.NO_SUCH_OBJECT, e:
 
            log.debug("LDAP says no such user '%s' (%s)", uid, username)
 
            raise LdapUsernameError()
 
        except ldap.INVALID_CREDENTIALS, e:
 
            log.debug("LDAP rejected password for user '%s' (%s)", uid, username)
 
            raise LdapPasswordError()
 
        except ldap.SERVER_DOWN, e:
 
            raise LdapConnectionError("LDAP can't access authentication server")
 

	
 
        return properties[0]
 

	
 
        return (dn, attrs)
rhodecode/lib/db_manage.py
Show inline comments
 
@@ -333,13 +333,16 @@ class DbManage(object):
 

	
 
    def create_ldap_options(self):
 
        """Creates ldap settings"""
 

	
 
        try:
 
            for k in ['ldap_active', 'ldap_host', 'ldap_port', 'ldap_ldaps',
 
                      'ldap_dn_user', 'ldap_dn_pass', 'ldap_base_dn']:
 
                      'ldap_tls_reqcert', 'ldap_dn_user', 'ldap_dn_pass',
 
                      'ldap_base_dn', 'ldap_filter', 'ldap_search_scope',
 
                      'ldap_attr_login', 'ldap_attr_firstname', 'ldap_attr_lastname',
 
                      'ldap_attr_email']:
 

	
 
                setting = RhodeCodeSettings(k, '')
 
                self.sa.add(setting)
 
            self.sa.commit()
 
        except:
 
            self.sa.rollback()
rhodecode/model/db.py
Show inline comments
 
@@ -102,13 +102,13 @@ class User(Base, BaseModel):
 
    active = Column("active", Boolean(), nullable=True, unique=None, default=None)
 
    admin = Column("admin", Boolean(), nullable=True, unique=None, default=False)
 
    name = Column("name", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    lastname = Column("lastname", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    email = Column("email", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 
    last_login = Column("last_login", DateTime(timezone=False), nullable=True, unique=None, default=None)
 
    is_ldap = Column("is_ldap", Boolean(), nullable=False, unique=None, default=False)
 
    ldap_dn = Column("ldap_dn", String(length=None, convert_unicode=False, assert_unicode=None), nullable=True, unique=None, default=None)
 

	
 
    user_log = relationship('UserLog', cascade='all')
 
    user_perms = relationship('UserToPerm', primaryjoin="User.user_id==UserToPerm.user_id", cascade='all')
 

	
 
    repositories = relationship('Repository')
 
    user_followers = relationship('UserFollowing', primaryjoin='UserFollowing.follows_user_id==User.user_id', cascade='all')
rhodecode/model/forms.py
Show inline comments
 
@@ -331,29 +331,20 @@ class LdapLibValidator(formencode.valida
 
        try:
 
            import ldap
 
        except ImportError:
 
            raise LdapImportError
 
        return value
 

	
 
class BaseDnValidator(formencode.validators.FancyValidator):
 
class AttrLoginValidator(formencode.validators.FancyValidator):
 

	
 
    def to_python(self, value, state):
 

	
 
        try:
 
            value % {'user':'valid'}
 

	
 
            if value.find('%(user)s') == -1:
 
                raise formencode.Invalid(_("You need to specify %(user)s in "
 
                                           "template for example uid=%(user)s "
 
                                           ",dc=company...") ,
 
                                         value, state)
 

	
 
        except KeyError:
 
            raise formencode.Invalid(_("Wrong template used, only %(user)s "
 
                                       "is an valid entry") ,
 
                                         value, state)
 
        if not value or not isinstance(value, (str, unicode)):
 
            raise formencode.Invalid(_("The LDAP Login attribute of the CN must be specified "
 
                                       "- this is the name of the attribute that is equivalent to 'username'"),
 
                                     value, state)
 

	
 
        return value
 

	
 
#===============================================================================
 
# FORMS        
 
#===============================================================================
 
@@ -518,20 +509,27 @@ def DefaultPermissionsForm(perms_choices
 
        default_register = OneOf(register_choices)
 
        default_create = OneOf(create_choices)
 

	
 
    return _DefaultPermissionsForm
 

	
 

	
 
def LdapSettingsForm():
 
def LdapSettingsForm(tls_reqcert_choices, search_scope_choices):
 
    class _LdapSettingsForm(formencode.Schema):
 
        allow_extra_fields = True
 
        filter_extra_fields = True
 
        pre_validators = [LdapLibValidator]
 
        ldap_active = StringBoolean(if_missing=False)
 
        ldap_host = UnicodeString(strip=True,)
 
        ldap_port = Number(strip=True,)
 
        ldap_ldaps = StringBoolean(if_missing=False)
 
        ldap_tls_reqcert = OneOf(tls_reqcert_choices)
 
        ldap_dn_user = UnicodeString(strip=True,)
 
        ldap_dn_pass = UnicodeString(strip=True,)
 
        ldap_base_dn = All(BaseDnValidator, UnicodeString(strip=True,))
 
        ldap_base_dn = UnicodeString(strip=True,)
 
        ldap_filter = UnicodeString(strip=True,)
 
        ldap_search_scope = OneOf(search_scope_choices)
 
        ldap_attr_login = All(AttrLoginValidator, UnicodeString(strip=True,))
 
        ldap_attr_firstname = UnicodeString(strip=True,)
 
        ldap_attr_lastname = UnicodeString(strip=True,)
 
        ldap_attr_email = UnicodeString(strip=True,)
 

	
 
    return _LdapSettingsForm
rhodecode/model/settings.py
Show inline comments
 
@@ -69,16 +69,24 @@ class SettingsModel(BaseModel):
 
        Returns ldap settings from database
 
        :returns:
 
        ldap_active
 
        ldap_host
 
        ldap_port 
 
        ldap_ldaps
 
        ldap_tls_reqcert
 
        ldap_dn_user 
 
        ldap_dn_pass 
 
        ldap_base_dn
 
        ldap_filter
 
        ldap_search_scope
 
        ldap_attr_login
 
        ldap_attr_firstname
 
        ldap_attr_lastname
 
        ldap_attr_email
 
        """
 
        # ldap_search_scope
 

	
 
        r = self.sa.query(RhodeCodeSettings)\
 
                .filter(RhodeCodeSettings.app_settings_name\
 
                        .startswith('ldap_'))\
 
                .all()
 

	
rhodecode/model/user.py
Show inline comments
 
@@ -72,31 +72,33 @@ class UserModel(BaseModel):
 
            self.sa.commit()
 
        except:
 
            log.error(traceback.format_exc())
 
            self.sa.rollback()
 
            raise
 

	
 
    def create_ldap(self, username, password):
 
    def create_ldap(self, username, password, user_dn, attrs):
 
        """
 
        Checks if user is in database, if not creates this user marked
 
        as ldap user
 
        :param username:
 
        :param password:
 
        :param user_dn:
 
        :param attrs:
 
        """
 
        from rhodecode.lib.auth import get_crypt_password
 
        log.debug('Checking for such ldap account in RhodeCode database')
 
        if self.get_by_username(username, case_insensitive=True) is None:
 
            try:
 
                new_user = User()
 
                new_user.username = username.lower()#add ldap account always lowercase
 
                new_user.username = username.lower() # add ldap account always lowercase
 
                new_user.password = get_crypt_password(password)
 
                new_user.email = '%s@ldap.server' % username
 
                new_user.email = attrs['email']
 
                new_user.active = True
 
                new_user.is_ldap = True
 
                new_user.name = '%s@ldap' % username
 
                new_user.lastname = ''
 
                new_user.ldap_dn = user_dn
 
                new_user.name = attrs['name']
 
                new_user.lastname = attrs['lastname']
 

	
 

	
 
                self.sa.add(new_user)
 
                self.sa.commit()
 
                return True
 
            except (DatabaseError,):
rhodecode/templates/admin/ldap/ldap.html
Show inline comments
 
@@ -18,45 +18,75 @@
 
<%def name="main()">
 
<div class="box">
 
    <!-- box / title -->
 
    <div class="title">
 
        ${self.breadcrumbs()}       
 
    </div>
 
    <h3>${_('LDAP administration')}</h3>
 
    ${h.form(url('ldap_settings'))}
 
    <div class="form">
 
        <div class="fields">
 

	
 
	  <h3>${_('Connection settings')}</h3>
 
            <div class="field">
 
                <div class="label label-checkbox"><label for="ldap_active">${_('Enable ldap')}</label></div>
 
                <div class="label label-checkbox"><label for="ldap_active">${_('Enable LDAP')}</label></div>
 
                <div class="checkboxes"><div class="checkbox">${h.checkbox('ldap_active',True,class_='small')}</div></div>
 
            </div>
 
            <div class="field">
 
                <div class="label"><label for="ldap_host">${_('Host')}</label></div>
 
                <div class="input">${h.text('ldap_host',class_='small')}</div>
 
            </div>
 
            <div class="field">
 
                <div class="label"><label for="ldap_port">${_('Port')}</label></div>
 
                <div class="input">${h.text('ldap_port',class_='small')}</div>
 
            </div>
 
            <div class="field">
 
                <div class="label label-checkbox"><label for="ldap_ldaps">${_('Enable LDAPS')}</label></div>
 
                <div class="checkboxes"><div class="checkbox">${h.checkbox('ldap_ldaps',True,class_='small')}</div></div>
 
            </div>
 
            <div class="field">
 
                <div class="label"><label for="ldap_dn_user">${_('Account')}</label></div>
 
                <div class="input">${h.text('ldap_dn_user',class_='small')}</div>
 
            </div>
 
            <div class="field">
 
                <div class="label"><label for="ldap_dn_pass">${_('Password')}</label></div>
 
                <div class="input">${h.password('ldap_dn_pass',class_='small')}</div>
 
            </div>
 
            <div class="field">
 
                <div class="label label-checkbox"><label for="ldap_ldaps">${_('Enable LDAPS')}</label></div>
 
                <div class="checkboxes"><div class="checkbox">${h.checkbox('ldap_ldaps',True,class_='small')}</div></div>
 
            </div>
 
            <div class="field">
 
                <div class="label"><label for="ldap_tls_reqcert">${_('Certificate Checks')}</label></div>
 
                <div class="select">${h.select('ldap_tls_reqcert',c.tls_reqcert_cur,c.tls_reqcert_choices,class_='small')}</div>
 
            </div>
 
	  <h3>${_('Search settings')}</h3>
 
            <div class="field">
 
                <div class="label"><label for="ldap_base_dn">${_('Base DN')}</label></div>
 
                <div class="input">${h.text('ldap_base_dn',class_='small')}</div>
 
            </div>
 
            <div class="field">
 
                <div class="label"><label for="ldap_filter">${_('LDAP Filter')}</label></div>
 
                <div class="input">${h.text('ldap_filter',class_='small')}</div>
 
            </div>
 
            <div class="field">
 
                <div class="label"><label for="ldap_search_scope">${_('LDAP Search Scope')}</label></div>
 
                <div class="select">${h.select('ldap_search_scope',c.search_scope_cur,c.search_scope_choices,class_='small')}</div>
 
            </div>
 
	  <h3>${_('Attribute mappings')}</h3>
 
            <div class="field">
 
                <div class="label"><label for="ldap_attr_login">${_('Login Attribute')}</label></div>
 
                <div class="input">${h.text('ldap_attr_login',class_='small')}</div>
 
            </div>
 
            <div class="field">
 
                <div class="label"><label for="ldap_attr_firstname">${_('First Name Attribute')}</label></div>
 
                <div class="input">${h.text('ldap_attr_firstname',class_='small')}</div>
 
            </div>
 
            <div class="field">
 
                <div class="label"><label for="ldap_attr_lastname">${_('Last Name Attribute')}</label></div>
 
                <div class="input">${h.text('ldap_attr_lastname',class_='small')}</div>
 
            </div>
 
            <div class="field">
 
                <div class="label"><label for="ldap_attr_email">${_('E-mail Attribute')}</label></div>
 
                <div class="input">${h.text('ldap_attr_email',class_='small')}</div>
 
            </div>
 
            
 
            <div class="buttons">
 
            ${h.submit('save','Save',class_="ui-button")}
 
            </div>              
 
        </div>
 
    </div>     
rhodecode/templates/admin/users/user_edit.html
Show inline comments
 
@@ -46,12 +46,21 @@
 
                    ${h.text('username',class_='medium')}
 
                </div>
 
             </div>
 
            
 
             <div class="field">
 
                <div class="label">
 
                    <label for="ldap_dn">${_('LDAP DN')}:</label>
 
                </div>
 
                <div class="input">
 
                    ${h.text('ldap_dn',class_='small')}
 
                </div>
 
             </div>
 
            
 
             <div class="field">
 
                <div class="label">
 
                    <label for="new_password">${_('New password')}:</label>
 
                </div>
 
                <div class="input">
 
                    ${h.password('new_password',class_='medium')}
 
                </div>
 
             </div>
 
@@ -228,7 +237,7 @@
 
                    choosen.options[i].selected = 'selected';
 
                }
 
            })  
 
        });
 
</script>    
 
</div>
 
</%def>  
 
\ No newline at end of file
 
</%def>
rhodecode/templates/admin/users/users.html
Show inline comments
 
@@ -46,13 +46,13 @@
 
                    <td>${h.link_to(user.username,h.url('edit_user', id=user.user_id))}</td>
 
                    <td>${user.name}</td>
 
                    <td>${user.lastname}</td>
 
                    <td>${user.last_login}</td>
 
                    <td>${h.bool2icon(user.active)}</td>
 
                    <td>${h.bool2icon(user.admin)}</td>
 
                    <td>${h.bool2icon(user.is_ldap)}</td>
 
                    <td>${h.bool2icon(bool(user.ldap_dn))}</td>
 
                    <td>
 
                        ${h.form(url('user', id=user.user_id),method='delete')}
 
                            ${h.submit('remove_','delete',id="remove_user_%s" % user.user_id,
 
                            class_="delete_icon action_button",onclick="return confirm('Confirm to delete this user');")}
 
                        ${h.end_form()}
 
                    </td>
0 comments (0 inline, 0 general)