Browse Source

User command: check LDAP user existence if LDAP enabled

Bastien Sevajol 9 years ago
parent
commit
e73aa6e429

+ 14 - 0
tracim/tracim/command/__init__.py View File

@@ -19,8 +19,22 @@ class BaseCommand(Command):
19 19
         try:
20 20
             super().run(parsed_args)
21 21
         except CommandAbortedError as exc:
22
+            if parsed_args.raise_error:
23
+                raise
22 24
             print(exc)
23 25
 
26
+    def get_parser(self, prog_name):
27
+        parser = super().get_parser(prog_name)
28
+
29
+        parser.add_argument(
30
+            "--raise",
31
+            help='Raise CommandAbortedError errors instead print it\'s message',
32
+            dest='raise_error',
33
+            action='store_true',
34
+        )
35
+
36
+        return parser
37
+
24 38
 
25 39
 class AppContextCommand(BaseCommand):
26 40
     """

+ 24 - 1
tracim/tracim/command/user.py View File

@@ -1,8 +1,10 @@
1 1
 # -*- coding: utf-8 -*-
2 2
 import transaction
3 3
 from sqlalchemy.exc import IntegrityError
4
+from tg import config
4 5
 
5 6
 from tracim.command import AppContextCommand, Extender
7
+from tracim.lib.auth.ldap import LDAPAuth
6 8
 from tracim.lib.exception import AlreadyExistError, CommandAbortedError
7 9
 from tracim.lib.group import GroupApi
8 10
 from tracim.lib.user import UserApi
@@ -88,7 +90,9 @@ class UserCommand(AppContextCommand):
88 90
 
89 91
     def _create_user(self, login, password, **kwargs):
90 92
         if not password:
91
-            raise CommandAbortedError("You must provide -p/--password parameter")
93
+            if self._password_required():
94
+                raise CommandAbortedError("You must provide -p/--password parameter")
95
+            password = ''
92 96
 
93 97
         try:
94 98
             user = User(email=login, password=password, **kwargs)
@@ -115,6 +119,8 @@ class UserCommand(AppContextCommand):
115 119
         print("User created/updated")
116 120
 
117 121
     def _proceed_user(self, parsed_args):
122
+        self._check_context(parsed_args)
123
+
118 124
         if self.action == self.ACTION_CREATE:
119 125
             try:
120 126
                 user = self._create_user(login=parsed_args.login, password=parsed_args.password)
@@ -137,6 +143,19 @@ class UserCommand(AppContextCommand):
137 143
         for group_name in parsed_args.remove_from_group:
138 144
             self._remove_user_from_named_group(user, group_name)
139 145
 
146
+    def _password_required(self):
147
+        if config.get('auth_type') == LDAPAuth.name:
148
+            return False
149
+        return True
150
+
151
+    def _check_context(self, parsed_args):
152
+        if config.get('auth_type') == LDAPAuth.name:
153
+            auth_instance = config.get('auth_instance')
154
+            if not auth_instance.ldap_auth.user_exist(parsed_args.login):
155
+                raise LDAPUserUnknown(
156
+                    "LDAP is enabled and user with login/email \"%s\" not found in LDAP" % parsed_args.login
157
+                )
158
+
140 159
 
141 160
 class CreateUserCommand(UserCommand):
142 161
     action = UserCommand.ACTION_CREATE
@@ -144,3 +163,7 @@ class CreateUserCommand(UserCommand):
144 163
 
145 164
 class UpdateUserCommand(UserCommand):
146 165
     action = UserCommand.ACTION_UPDATE
166
+
167
+
168
+class LDAPUserUnknown(CommandAbortedError):
169
+    pass

+ 17 - 1
tracim/tracim/lib/auth/ldap.py View File

@@ -1,7 +1,7 @@
1 1
 # -*- coding: utf-8 -*-
2 2
 import transaction
3 3
 from tg.configuration.auth import TGAuthMetadata
4
-from who_ldap import LDAPAttributesPlugin as BaseLDAPAttributesPlugin
4
+from who_ldap import LDAPAttributesPlugin as BaseLDAPAttributesPlugin, make_connection
5 5
 from who_ldap import LDAPGroupsPlugin as BaseLDAPGroupsPlugin
6 6
 from who_ldap import LDAPSearchAuthenticatorPlugin as BaseLDAPSearchAuthenticatorPlugin
7 7
 
@@ -115,6 +115,22 @@ class LDAPSearchAuthenticatorPlugin(BaseLDAPSearchAuthenticatorPlugin):
115 115
         DBSession.flush()
116 116
         transaction.commit()
117 117
 
118
+    def user_exist(self, email):
119
+        with make_connection(self.url, self.bind_dn, self.bind_pass) as conn:
120
+            if self.start_tls:
121
+                conn.start_tls()
122
+
123
+            if not conn.bind():
124
+                return False
125
+
126
+            search = self.search_pattern % email
127
+            conn.search(self.base_dn, search, self.search_scope)
128
+
129
+            if len(conn.response) > 0:
130
+                return True
131
+
132
+            return False
133
+
118 134
 
119 135
 class LDAPApplicationAuthMetadata(TGAuthMetadata):
120 136
 

+ 1 - 17
tracim/tracim/tests/__init__.py View File

@@ -176,26 +176,10 @@ class TestStandard(object):
176 176
 
177 177
 
178 178
 class TestCommand(TestStandard):
179
-    def __init__(self, *args, **kwargs):
180
-        super().__init__(*args, **kwargs)
181
-        # We disable app loading from commands classes
182
-        BaseCommand.auto_setup_app = False
183
-        # Hack parser object to test conditions
184
-        BaseCommand.get_parser = self._get_test_parser()
185
-
186
-    def _get_test_parser(self):
187
-        def get_parser(self, prog_name):
188
-            parser = ArgumentParser(
189
-                description=self.get_description(),
190
-                prog=prog_name,
191
-                add_help=False
192
-            )
193
-            return parser
194
-        return get_parser
195
-
196 179
     def _execute_command(self, command_class, command_name, sub_argv):
197 180
         parser = argparse.ArgumentParser()
198 181
         command = command_class(self.app, parser)
182
+        command.auto_setup_app = False
199 183
         cmd_parser = command.get_parser(command_name)
200 184
         parsed_args = cmd_parser.parse_args(sub_argv)
201 185
         return command.run(parsed_args)

+ 33 - 0
tracim/tracim/tests/command/user_ldap.py View File

@@ -0,0 +1,33 @@
1
+from nose.tools import eq_, raises
2
+from nose.tools import ok_
3
+
4
+from tracim.command.user import CreateUserCommand, LDAPUserUnknown
5
+from tracim.fixtures.ldap import ldap_test_server_fixtures
6
+from tracim.lib.exception import CommandAbortedError
7
+from tracim.tests import TestCommand, LDAPTest
8
+
9
+
10
+class TestLDAPUserCommand(LDAPTest, TestCommand):
11
+    """
12
+    Test LDAP user verification when execute command
13
+    """
14
+    application_under_test = 'ldap'
15
+    ldap_server_data = ldap_test_server_fixtures
16
+
17
+    @raises(LDAPUserUnknown)
18
+    def test_user_not_in_ldap(self):
19
+        self._execute_command(
20
+            CreateUserCommand,
21
+            'gearbox user create',
22
+            ['-l', 'unknown-user@fsf.org', '-p', 'foo', '--raise']
23
+        )
24
+
25
+    def test_user_in_ldap(self):
26
+        try:
27
+            self._execute_command(
28
+                CreateUserCommand,
29
+                'gearbox user create',
30
+                ['-l', 'richard-not-real-email@fsf.org', '-p', 'foo', '--raise']
31
+            )
32
+        except LDAPUserUnknown:
33
+            ok_(False, "Command should not raise LDAPUserUnknown exception")