Opened 13 years ago

Closed 3 years ago

Last modified 3 years ago

#39 closed task (fixed)

Enable trac email lookup in ldap

Reported by: warmerdam Owned by: strk
Priority: major Milestone:
Component: Trac Keywords:
Cc: hobu

Description

Please do something so that Trac will automatically lookup email addresses for authenticated users in LDAP if they haven't set one themselves via "settings".

Change History (16)

comment:1 Changed 13 years ago by warmerdam

Owner: changed from hobu to warmerdam

I'll take this one...

comment:2 Changed 13 years ago by warmerdam

Resolution: fixed
Status: newclosed

OK, I have modified /usr/lib/python2.3/site-packages/trac/notification.py by applying this diff:

[root@osgeo1 trac]# diff notification.py ~warmerdam/notification.py 29a30,53

def osgeo_ldap_email_lookup( uid ):

server = 'localhost' who = 'cn=Manager,dc=osgeo,dc=org' cred = '<manager_password>'

try:

import ldap

l = ldap.open(server) l.simple_bind_s(who,cred)

base = 'uid='+uid+',ou=people,dc=osgeo,dc=org' scope = ldap.SCOPE_BASE result = l.search_s( base, scope, attrlist = mail? )

if len(result) != 1:

return None

dn, attrdict = result[0]

return attrdictmail?[0]

except:

return None

246,254c270,288 < elif NotifyEmail?.nodomaddr_re.match(address): < if self.config.getbool('notification', 'use_short_addr'): < return address < domain = self.config.get('notification', 'smtp_default_domain') < if domain: < address = "%s@%s" % (address, domain) < else: < self.env.log.info("Email address w/o domain: %s" % address) < return None ---

else:

ldap_addr = osgeo_ldap_email_lookup( address ) if ldap_addr is None:

self.env.log.debug("ldap lookup failed.")

if ldap_addr is not None:

self.env.log.debug("Using ldap email %s for uid %s" % (ldap_addr,address)) address = ldap_addr # it would be nice to push this association into # the session info, but a bit tricky...

elif NotifyEmail?.nodomaddr_re.match(address):

if self.config.getbool('notification', 'use_short_addr'):

return address

domain = self.config.get('notification', 'smtp_default_domain') if domain:

address = "%s@%s" % (address, domain)

else:

self.env.log.info("Email address w/o domain: %s" % address) return None

This seems to do the trick, though at the cost of an ldap lookup for every email address something is sent to. A copy of the modified notification.py is in ~warmerdam.

Keep in mind this is yet another place with the ldap manager password hardcoded.

comment:3 Changed 13 years ago by warmerdam

Lets try that patch again with better wiki formatting:

[root@osgeo1 trac]# diff notification.py ~warmerdam/notification.py
29a30,53
> def osgeo_ldap_email_lookup( uid ):
> 
>     server = 'localhost'
>     who = 'cn=Manager,dc=osgeo,dc=org'
>     cred = 'testdap'
> 
>     try:
>         import ldap
> 
>         l = ldap.open(server)
>         l.simple_bind_s(who,cred)
> 
>         base = 'uid='+uid+',ou=people,dc=osgeo,dc=org'
>         scope = ldap.SCOPE_BASE
>         result = l.search_s( base, scope, attrlist = ['mail'] )
> 
>         if len(result) != 1:
>             return None
> 
>         dn, attrdict = result[0]
> 
>         return attrdict['mail'][0]
>     except:
>         return None
246,254c270,288
<             elif NotifyEmail.nodomaddr_re.match(address):
<                 if self.config.getbool('notification', 'use_short_addr'):
<                     return address
<                 domain = self.config.get('notification', 'smtp_default_domain')
<                 if domain:
<                     address = "%s@%s" % (address, domain)
<                 else:
<                     self.env.log.info("Email address w/o domain: %s" % address)
<                     return None
---
>             else:
>                 ldap_addr = osgeo_ldap_email_lookup( address )
>                 if ldap_addr is None:
>                     self.env.log.debug("ldap lookup failed.")
>                 if ldap_addr is not None:
>                     self.env.log.debug("Using ldap email %s for uid %s" % (ldap_addr
,address))
>                     address = ldap_addr
>                     # it would be nice to push this association into
>                     # the session info, but a bit tricky...
>                 elif NotifyEmail.nodomaddr_re.match(address):
>                     if self.config.getbool('notification', 'use_short_addr'):
>                         return address
>                     domain = self.config.get('notification', 'smtp_default_domain')
>                     if domain:
>                         address = "%s@%s" % (address, domain)
>                     else:
>                         self.env.log.info("Email address w/o domain: %s" % address)
>                         return None
>                     

comment:4 Changed 13 years ago by warmerdam

The script has been altered slightly to bind anonymously now, rather than as manager. Howard has changed the configuration of the ldap somewhat to allow this.

comment:5 Changed 12 years ago by hobu

Cc: hobu added

comment:6 Changed 4 years ago by warmerdam

Updated to Trac 1.0.5 and the following change was made to :/usr/local/lib/python2.6/dist-packages/Trac-1.0.5-py2.6.egg/trac/notification.py:

277,297d276
< def osgeo_ldap_email_lookup( uid ):
<     server = 'ldaps://ldap.osgeo.org'
< 
<     try:
<         import ldap
< 
<         l = ldap.initialize(server)
<         l.simple_bind_s('')
< 
<         base = 'uid='+uid+',ou=people,dc=osgeo,dc=org'
<         scope = ldap.SCOPE_BASE
<         result = l.search_s( base, scope, attrlist = ['mail'] )
< 
<         if len(result) != 1:
<             return None
< 
<         dn, attrdict = result[0]
< 
<         return attrdict['mail'][0]
<     except:
<         return None
435,453c414,422
<         else:
<             ldap_addr = osgeo_ldap_email_lookup( address )
<             if ldap_addr is None:
<                 self.env.log.debug("ldap lookup failed.")
<             if ldap_addr is not None:
<                 self.env.log.debug("Using ldap email %s for uid %s" % (ldap_addr
< ,address))
<                 address = ldap_addr
<                 # it would be nice to push this association into
<                 # the session info, but a bit tricky...
< 	    elif not is_email(address) and NotifyEmail.nodomaddr_re.match(address):
<                 if self.config.getbool('notification', 'use_short_addr'):
<                     return address
<                 domain = self.config.get('notification', 'smtp_default_domain')
<                 if domain:
<                     address = "%s@%s" % (address, domain)
<                 else:
<                     self.env.log.info("Email address w/o domain: %s", address)
<                     return None
---
>         elif not is_email(address) and NotifyEmail.nodomaddr_re.match(address):
>             if self.config.getbool('notification', 'use_short_addr'):
>                 return address
>             domain = self.config.get('notification', 'smtp_default_domain')
>             if domain:
>                 address = "%s@%s" % (address, domain)
>             else:
>                 self.env.log.info("Email address w/o domain: %s", address)
>                 return None

comment:7 Changed 4 years ago by strk

What does the Trac-1.0.5-py2.6.egg modification do exactly, why is it needed ? I'd like to update the corresponding section on the wiki: https://wiki.osgeo.org/wiki/Trac_Instances#Local_Customizations

Is there a SAC repository to put these changes in ?

comment:8 Changed 3 years ago by strk

NOTE: broken on upgrade to 1.0.x: #1671

comment:9 Changed 3 years ago by strk

For the record, the patch updated for 1.0.5 (and now in place):

tracsvn:/usr/local/lib/python2.6/dist-packages/Trac-1.0.5-py2.6.egg/trac# diff notification.py.000  notification.py
41a42,66
> def osgeo_ldap_email_lookup( uid ):
>
>     server = 'localhost'
>     who = 'cn=Manager,dc=osgeo,dc=org'
>     cred = 'testdap'
>
>     try:
>         import ldap
>
>         l = ldap.initialize('ldaps://ldap.osgeo.org')
>         l.simple_bind_s('')
>
>         base = 'uid='+uid+',ou=people,dc=osgeo,dc=org'
>         scope = ldap.SCOPE_BASE
>         result = l.search_s( base, scope, attrlist = ['mail'] )
>
>         if len(result) != 1:
>             return None
>
>         dn, attrdict = result[0]
>
>         return attrdict['mail'][0]
>     except:
>         return None
>
414,422c439,456
<         elif not is_email(address) and NotifyEmail.nodomaddr_re.match(address):
<             if self.config.getbool('notification', 'use_short_addr'):   
<                 return address
<             domain = self.config.get('notification', 'smtp_default_domain')
<             if domain:
<                 address = "%s@%s" % (address, domain)
<             else:
<                 self.env.log.info("Email address w/o domain: %s", address)
<                 return None
---
>         elif not is_email(address):
>                 ldap_addr = osgeo_ldap_email_lookup( address )
>                 if ldap_addr is None:
>                     self.env.log.debug("ldap lookup failed.")
>                 if ldap_addr is not None:
>                     self.env.log.debug("Using ldap email %s for uid %s" % (ldap_addr,address))
>                     address = ldap_addr
>                     # it would be nice to push this association into
>                     # the session info, but a bit tricky...
>                 elif NotifyEmail.nodomaddr_re.match(address):
>                     if self.config.getbool('notification', 'use_short_addr'):
>                         return address
>                     domain = self.config.get('notification', 'smtp_default_domain')
>                     if domain:
>                         address = "%s@%s" % (address, domain)
>                     else:
>                         self.env.log.info("Email address w/o domain: %s" % address)
>                         return None

comment:10 Changed 3 years ago by strk

I found an old Trac ticket requesting a solution to this same feature: https://trac.edgewall.org/ticket/3162 -- as we move toward another upgrade to 1.2 (#1816) it would be nice to finally drop local modifications

comment:11 Changed 3 years ago by strk

Trac 1.2 (to be updated to, see #1816) made it possible to resolve email via a plugin. See https://trac.edgewall.org/wiki/TracDev/PluginDevelopment/ExtensionPoints/trac.notification.api.IEmailAddressResolver -- we'll need to test such plugin before upgrade

comment:12 Changed 3 years ago by strk

Component: Systems AdminTrac
Resolution: fixed
Status: closedreopened

comment:13 Changed 3 years ago by strk

Owner: changed from warmerdam to strk
Status: reopenednew

I'm looking at implementing proper LDAP lookup for email. Some more info can be read in https://trac.edgewall.org/ticket/3162#comment:16

comment:15 Changed 3 years ago by strk

Resolution: fixed
Status: newclosed

Fix landed in Trac 1.2.1dev: https://trac.edgewall.org/changeset/15356 Closing as it will be resolved by upgrading to Trac 1.2.1dev (revision 15356 or later). Trac upgrade ticket is #1816, LDAP email lookup will be implemented by plugin https://git.osgeo.org/gogs/sac/TracLDAPEmailResolverPlugin

comment:16 Changed 3 years ago by strk

Ticket #1863 is about restoring the behavior previously obtained by patches included in this ticket, which was modified after upgrading Trac to 1.2 (#1816)

Note: See TracTickets for help on using tickets.