Browse Source

better login view and better user_api related : authenticate_user method

Guénaël Muller 6 years ago
parent
commit
eb3b6c3067
3 changed files with 50 additions and 32 deletions
  1. 5 1
      tracim/exceptions.py
  2. 33 13
      tracim/lib/core/user.py
  3. 12 18
      tracim/views/core_api/session_controller.py

+ 5 - 1
tracim/exceptions.py View File

@@ -85,5 +85,9 @@ class DigestAuthNotImplemented(Exception):
85 85
     pass
86 86
 
87 87
 
88
-class LoginFailed(TracimException):
88
+class AuthenticationFailed(TracimException):
89
+    pass
90
+
91
+
92
+class BadUserPassword(TracimException):
89 93
     pass

+ 33 - 13
tracim/lib/core/user.py View File

@@ -5,6 +5,9 @@ import transaction
5 5
 import typing as typing
6 6
 
7 7
 from tracim.models.auth import User
8
+from sqlalchemy.orm.exc import NoResultFound
9
+from tracim.exceptions import BadUserPassword
10
+from tracim.exceptions import AuthenticationFailed
8 11
 
9 12
 
10 13
 class UserApi(object):
@@ -14,21 +17,46 @@ class UserApi(object):
14 17
         self._user = current_user
15 18
         self._config = config
16 19
 
17
-    def get_all(self):
18
-        return self._session.query(User).order_by(User.display_name).all()
19
-
20 20
     def _base_query(self):
21 21
         return self._session.query(User)
22 22
 
23
-    def get_one(self, user_id: int):
23
+    def get_one(self, user_id: int) -> User:
24 24
         return self._base_query().filter(User.user_id==user_id).one()
25 25
 
26
-    def get_one_by_email(self, email: str):
26
+    def get_one_by_email(self, email: str) -> User:
27 27
         return self._base_query().filter(User.email==email).one()
28 28
 
29 29
     def get_one_by_id(self, id: int) -> User:
30 30
         return self._base_query().filter(User.user_id==id).one()
31 31
 
32
+    def get_all(self) -> typing.Iterable[User]:
33
+        return self._session.query(User).order_by(User.display_name).all()
34
+
35
+    def user_with_email_exists(self, email: str):
36
+        try:
37
+            self.get_one_by_email(email)
38
+            return True
39
+        # TODO - G.M - 09-04-2018 - Better exception
40
+        except:
41
+            return False
42
+
43
+    def authenticate_user(self, email, password) -> User:
44
+        """
45
+        Authenticate user with email and password, raise AuthenticationFailed
46
+        if uncorrect.
47
+        :param email: email of the user
48
+        :param password: cleartext password of the user
49
+        :return: User who was authenticated.
50
+        """
51
+        try:
52
+            user = self.get_one_by_email(email)
53
+            if user.validate_password(password):
54
+                return user
55
+            else:
56
+                raise BadUserPassword()
57
+        except (BadUserPassword, NoResultFound):
58
+            raise AuthenticationFailed
59
+
32 60
     def update(
33 61
             self,
34 62
             user: User,
@@ -48,14 +76,6 @@ class UserApi(object):
48 76
         if do_save:
49 77
             self.save(user)
50 78
 
51
-    def user_with_email_exists(self, email: str):
52
-        try:
53
-            self.get_one_by_email(email)
54
-            return True
55
-        # TODO - G.M - 09-04-2018 - Better exception
56
-        except:
57
-            return False
58
-
59 79
     def create_user(self, email=None, groups=[], save_now=False) -> User:
60 80
         user = User()
61 81
 

+ 12 - 18
tracim/views/core_api/session_controller.py View File

@@ -14,10 +14,13 @@ from tracim.views.controllers import Controller
14 14
 from pyramid.config import Configurator
15 15
 
16 16
 from tracim.views import BASE_API_V2
17
-from tracim.views.core_api.schemas import UserSchema, NoContentSchema
17
+from tracim.views.core_api.schemas import UserSchema
18
+from tracim.views.core_api.schemas import NoContentSchema
19
+
18 20
 from tracim.views.core_api.schemas import LoginOutputHeaders
19 21
 from tracim.views.core_api.schemas import BasicAuthSchema
20
-from tracim.exceptions import NotAuthentificated, LoginFailed
22
+from tracim.exceptions import NotAuthentificated
23
+from tracim.exceptions import AuthenticationFailed
21 24
 
22 25
 try:  # Python 3.5+
23 26
     from http import HTTPStatus
@@ -30,7 +33,7 @@ class SessionController(Controller):
30 33
     @hapic.with_api_doc()
31 34
     @hapic.input_headers(LoginOutputHeaders())
32 35
     @hapic.input_body(BasicAuthSchema())
33
-    @hapic.handle_exception(LoginFailed, http_code=HTTPStatus.BAD_REQUEST)
36
+    @hapic.handle_exception(AuthenticationFailed, http_code=HTTPStatus.BAD_REQUEST)
34 37
     # TODO - G.M - 17-04-2018 - fix output header ?
35 38
     # @hapic.output_headers()
36 39
     @hapic.output_body(
@@ -44,21 +47,12 @@ class SessionController(Controller):
44 47
         email = request.json_body['email']
45 48
         password = request.json_body['password']
46 49
         app_config = request.registry.settings['CFG']
47
-        try:
48
-            uapi = UserApi(
49
-                None,
50
-                session=request.dbsession,
51
-                config=app_config,
52
-            )
53
-            user = uapi.get_one_by_email(email)
54
-            valid_password = user.validate_password(password)
55
-            if not valid_password:
56
-                # Bad password
57
-                raise LoginFailed('Bad Credentials')
58
-        except NoResultFound:
59
-            # User does not exist
60
-            raise LoginFailed('Bad Credentials')
61
-        return
50
+        uapi = UserApi(
51
+            None,
52
+            session=request.dbsession,
53
+            config=app_config,
54
+        )
55
+        return uapi.authenticate_user(email, password)
62 56
 
63 57
     @hapic.with_api_doc()
64 58
     @hapic.output_body(