浏览代码

LDAP: upodate user attr with ldap attr

Bastien Sevajol 9 年前
父节点
当前提交
933609f740

+ 1 - 1
tracim/test.ini 查看文件

31
 ldap_bind_dn = cn=admin,dc=directory,dc=fsf,dc=org
31
 ldap_bind_dn = cn=admin,dc=directory,dc=fsf,dc=org
32
 ldap_bind_pass = toor
32
 ldap_bind_pass = toor
33
 ldap_ldap_naming_attribute = uid
33
 ldap_ldap_naming_attribute = uid
34
-ldap_user_attributes = mail=email
34
+ldap_user_attributes = mail=email,pubname=display_name
35
 ldap_tls = False
35
 ldap_tls = False
36
 ldap_group_enabled = False
36
 ldap_group_enabled = False
37
 use = config:development.ini
37
 use = config:development.ini

+ 4 - 2
tracim/tracim/fixtures/ldap.py 查看文件

40
             'attributes': {
40
             'attributes': {
41
                 'uid': 'richard-not-real-email@fsf.org',
41
                 'uid': 'richard-not-real-email@fsf.org',
42
                 'userPassword': 'rms',
42
                 'userPassword': 'rms',
43
-                'mail': 'richard-not-real-email@fsf.org'
43
+                'mail': 'richard-not-real-email@fsf.org',
44
+                'pubname': 'Richard Stallman',
44
             }
45
             }
45
         },
46
         },
46
         {
47
         {
49
             'attributes': {
50
             'attributes': {
50
                 'uid': 'lawrence-not-real-email@fsf.org',
51
                 'uid': 'lawrence-not-real-email@fsf.org',
51
                 'userPassword': 'foobarbaz',
52
                 'userPassword': 'foobarbaz',
52
-                'mail': 'lawrence-not-real-email@fsf.org'
53
+                'mail': 'lawrence-not-real-email@fsf.org',
54
+                'pubname': 'Lawrence Lessig',
53
             }
55
             }
54
         },
56
         },
55
     ]
57
     ]

+ 20 - 9
tracim/tracim/lib/auth/ldap.py 查看文件

1
 # -*- coding: utf-8 -*-
1
 # -*- coding: utf-8 -*-
2
+import transaction
2
 from tg.configuration.auth import TGAuthMetadata
3
 from tg.configuration.auth import TGAuthMetadata
3
 from who_ldap import LDAPAttributesPlugin as BaseLDAPAttributesPlugin
4
 from who_ldap import LDAPAttributesPlugin as BaseLDAPAttributesPlugin
4
 from who_ldap import LDAPGroupsPlugin as BaseLDAPGroupsPlugin
5
 from who_ldap import LDAPGroupsPlugin as BaseLDAPGroupsPlugin
92
         # Note: super().authenticate return None if already authenticated or not found
93
         # Note: super().authenticate return None if already authenticated or not found
93
         email = super().authenticate(environ, identity)
94
         email = super().authenticate(environ, identity)
94
         if email:
95
         if email:
95
-            self._sync_ldap_user(email)
96
+            self._sync_ldap_user(email, environ, identity)
96
         return email
97
         return email
97
 
98
 
98
-    def _sync_ldap_user(self, email):
99
+    def _sync_ldap_user(self, email, environ, identity):
100
+        # Create or get user for connected email
99
         if not self._user_api.user_with_email_exists(email):
101
         if not self._user_api.user_with_email_exists(email):
100
             user = User(email=email, imported_from=LDAPAuth.name)
102
             user = User(email=email, imported_from=LDAPAuth.name)
101
             DBSession.add(user)
103
             DBSession.add(user)
102
-            import transaction
103
-            transaction.commit()
104
+        else:
105
+            user = self._user_api.get_one_by_email(email)
106
+
107
+        # Retrieve ldap user attributes
108
+        self._auth.ldap_user_provider.add_metadata_for_auth(environ, identity)
104
 
109
 
105
-            # TODO - B.S. - 20160208: Voir avec Damien, si je ne fait pas de transaction.commit()
106
-            # manuellement la donnée n'est pas en base.
107
-            # self._user_api.create_user(email=email, save_now=True)
110
+        # Update user with ldap attributes
111
+        user_ldap_values = identity.get('user').copy()
112
+        for field_name in user_ldap_values:
113
+            setattr(user, field_name, user_ldap_values[field_name])
114
+
115
+        DBSession.flush()
116
+        transaction.commit()
108
 
117
 
109
 
118
 
110
 class LDAPApplicationAuthMetadata(TGAuthMetadata):
119
 class LDAPApplicationAuthMetadata(TGAuthMetadata):
156
         self._user_api = UserApi(None)
165
         self._user_api = UserApi(None)
157
 
166
 
158
     def add_metadata(self, environ, identity):
167
     def add_metadata(self, environ, identity):
168
+        # We disable metadata recuperation, we do it at connection in LDAPSearchAuthenticatorPlugin._sync_ldap_user
169
+        return
170
+
171
+    def add_metadata_for_auth(self, environ, identity):
159
         super().add_metadata(environ, identity)
172
         super().add_metadata(environ, identity)
160
-        # TODO - B.S. - 20160212: identity contains now som information from LDAP what we can save in local database
161
-        identity[self.name] = self._user_api.get_one_by_email(identity.get('repoze.who.userid'))
162
 
173
 
163
     @property
174
     @property
164
     def local_fields(self):
175
     def local_fields(self):

+ 18 - 1
tracim/tracim/tests/__init__.py 查看文件

1
 # -*- coding: utf-8 -*-
1
 # -*- coding: utf-8 -*-
2
 """Unit and functional test suite for tracim."""
2
 """Unit and functional test suite for tracim."""
3
 import argparse
3
 import argparse
4
+import os
4
 from os import getcwd
5
 from os import getcwd
5
 
6
 
6
 import ldap3
7
 import ldap3
7
 import tg
8
 import tg
9
+import time
8
 import transaction
10
 import transaction
9
 from gearbox.commands.setup_app import SetupAppCommand
11
 from gearbox.commands.setup_app import SetupAppCommand
10
 from ldap_test import LdapServer
12
 from ldap_test import LdapServer
20
 from sqlalchemy.schema import Table
22
 from sqlalchemy.schema import Table
21
 from tg import config
23
 from tg import config
22
 from tg.util import Bunch
24
 from tg.util import Bunch
23
-from webtest import TestApp
25
+from webtest import TestApp as BaseTestApp, AppError
24
 from who_ldap import make_connection
26
 from who_ldap import make_connection
25
 
27
 
26
 from tracim.command import BaseCommand
28
 from tracim.command import BaseCommand
32
 application_name = 'main_without_authn'
34
 application_name = 'main_without_authn'
33
 
35
 
34
 
36
 
37
+class TestApp(BaseTestApp):
38
+    def _check_status(self, status, res):
39
+        """ Simple override to print html content when error"""
40
+        try:
41
+            super()._check_status(status, res)
42
+        except AppError as exc:
43
+            dump_file_path = "/tmp/debug_%d_%s.html" % (time.time() * 1000, res.request.path_qs[1:])
44
+            if os.path.exists("/tmp"):
45
+                with open(dump_file_path, 'w') as dump_file:
46
+                    print(res.ubody, file=dump_file)
47
+                # Update exception message with info about this dumped file
48
+                exc.args = ('%s html error file dump in %s' % (exc.args[0], dump_file_path), ) + exc.args[1:]
49
+            raise exc
50
+
51
+
35
 def load_app(name=application_name):
52
 def load_app(name=application_name):
36
     """Load the test application."""
53
     """Load the test application."""
37
     return TestApp(loadapp('config:test.ini#%s' % name, relative_to=getcwd()))
54
     return TestApp(loadapp('config:test.ini#%s' % name, relative_to=getcwd()))

+ 14 - 1
tracim/tracim/tests/functional/test_ldap_authentication.py 查看文件

3
 Integration tests for the ldap authentication sub-system.
3
 Integration tests for the ldap authentication sub-system.
4
 """
4
 """
5
 from tracim.fixtures.ldap import ldap_test_server_fixtures
5
 from tracim.fixtures.ldap import ldap_test_server_fixtures
6
-from nose.tools import eq_
6
+from nose.tools import eq_, ok_
7
 
7
 
8
 from tracim.model import DBSession, User
8
 from tracim.model import DBSession, User
9
 from tracim.tests import LDAPTest, TracimTestController
9
 from tracim.tests import LDAPTest, TracimTestController
39
 
39
 
40
         # User is registered in tracim database
40
         # User is registered in tracim database
41
         eq_(1, DBSession.query(User).filter(User.email == 'richard-not-real-email@fsf.org').count())
41
         eq_(1, DBSession.query(User).filter(User.email == 'richard-not-real-email@fsf.org').count())
42
+
43
+    def test_ldap_attributes_sync(self):
44
+        # User is already know in database
45
+        eq_(1, DBSession.query(User).filter(User.email == 'lawrence-not-real-email@fsf.org').count())
46
+
47
+        # His display name is Lawrence L.
48
+        lawrence = DBSession.query(User).filter(User.email == 'lawrence-not-real-email@fsf.org').one()
49
+        eq_('Lawrence L.', lawrence.display_name)
50
+
51
+        # After connexion with LDAP, his display_name is updated (see ldap fixtures)
52
+        self._connect_user('lawrence-not-real-email@fsf.org', 'foobarbaz')
53
+        lawrence = DBSession.query(User).filter(User.email == 'lawrence-not-real-email@fsf.org').one()
54
+        eq_('Lawrence Lessig', lawrence.display_name)

+ 1 - 1
tracim/tracim/tests/functional/test_ldap_restrictions.py 查看文件

59
 
59
 
60
         # If we force edit of user, "email" field will be not updated
60
         # If we force edit of user, "email" field will be not updated
61
         eq_(lawrence.email, 'lawrence-not-real-email@fsf.org')
61
         eq_(lawrence.email, 'lawrence-not-real-email@fsf.org')
62
-        eq_(lawrence.display_name, 'Lawrence Lessig')
62
+        eq_(lawrence.display_name, 'Lawrence L.')
63
 
63
 
64
         try_post_user = self.app.post(
64
         try_post_user = self.app.post(
65
             '/user/%d?_method=PUT' % lawrence.user_id,
65
             '/user/%d?_method=PUT' % lawrence.user_id,

+ 1 - 1
tracim/tracim/websetup/bootstrap.py 查看文件

43
         # TODO: - B.S. - 20160212: Following fixture is LDAP tests specific, should make an little fixture management
43
         # TODO: - B.S. - 20160212: Following fixture is LDAP tests specific, should make an little fixture management
44
         # for tests
44
         # for tests
45
         lawrence = model.User()
45
         lawrence = model.User()
46
-        lawrence.display_name = 'Lawrence Lessig'
46
+        lawrence.display_name = 'Lawrence L.'
47
         lawrence.email = 'lawrence-not-real-email@fsf.org'
47
         lawrence.email = 'lawrence-not-real-email@fsf.org'
48
         lawrence.password = 'foobarbaz'
48
         lawrence.password = 'foobarbaz'
49
         model.DBSession.add(lawrence)
49
         model.DBSession.add(lawrence)