Selaa lähdekoodia

Simpler controller code with some refactoring

Guénaël Muller 6 vuotta sitten
vanhempi
commit
cc602e1f03

+ 11 - 3
tracim/lib/core/user.py Näytä tiedosto

46
         """
46
         """
47
         Get one user by user id
47
         Get one user by user id
48
         """
48
         """
49
-        return self._base_query().filter(User.user_id == user_id).one()
49
+        try:
50
+            user = self._base_query().filter(User.user_id == user_id).one()
51
+        except NoResultFound:
52
+            raise UserNotExist()
53
+        return user
50
 
54
 
51
     def get_one_by_email(self, email: str) -> User:
55
     def get_one_by_email(self, email: str) -> User:
52
         """
56
         """
54
         :param email: Email of the user
58
         :param email: Email of the user
55
         :return: one user
59
         :return: one user
56
         """
60
         """
57
-        return self._base_query().filter(User.email == email).one()
61
+        try:
62
+            user = self._base_query().filter(User.email == email).one()
63
+        except NoResultFound:
64
+            raise UserNotExist()
65
+        return user
58
 
66
 
59
     # FIXME - G.M - 24-04-2018 - Duplicate method with get_one.
67
     # FIXME - G.M - 24-04-2018 - Duplicate method with get_one.
60
     def get_one_by_id(self, id: int) -> User:
68
     def get_one_by_id(self, id: int) -> User:
95
                 return user
103
                 return user
96
             else:
104
             else:
97
                 raise WrongUserPassword()
105
                 raise WrongUserPassword()
98
-        except (WrongUserPassword, NoResultFound):
106
+        except (WrongUserPassword, NoResultFound, UserNotExist):
99
             raise AuthenticationFailed()
107
             raise AuthenticationFailed()
100
 
108
 
101
     def can_see_private_info_of_user(self, user: User):
109
     def can_see_private_info_of_user(self, user: User):

+ 4 - 4
tracim/lib/core/userworkspace.py Näytä tiedosto

120
         return self._session.query(UserRoleInWorkspace)\
120
         return self._session.query(UserRoleInWorkspace)\
121
             .filter(UserRoleInWorkspace.user_id == user_id)
121
             .filter(UserRoleInWorkspace.user_id == user_id)
122
 
122
 
123
-    def get_all_for_user(self, user_id):
124
-        return self._get_all_for_user(user_id).all()
123
+    def get_all_for_user(self, user: User):
124
+        return self._get_all_for_user(user.user_id).all()
125
 
125
 
126
     def get_all_for_user_order_by_workspace(
126
     def get_all_for_user_order_by_workspace(
127
             self,
127
             self,
130
         return self._get_all_for_user(user_id)\
130
         return self._get_all_for_user(user_id)\
131
             .join(UserRoleInWorkspace.workspace).order_by(Workspace.label).all()
131
             .join(UserRoleInWorkspace.workspace).order_by(Workspace.label).all()
132
 
132
 
133
-    def get_all_for_workspace(self, workspace_id):
133
+    def get_all_for_workspace(self, workspace:Workspace):
134
         return self._session.query(UserRoleInWorkspace)\
134
         return self._session.query(UserRoleInWorkspace)\
135
-            .filter(UserRoleInWorkspace.workspace_id == workspace_id).all()
135
+            .filter(UserRoleInWorkspace.workspace_id == workspace.workspace_id).all()  # nopep8
136
 
136
 
137
     def save(self, role: UserRoleInWorkspace):
137
     def save(self, role: UserRoleInWorkspace):
138
         self._session.flush()
138
         self._session.flush()

+ 2 - 1
tracim/lib/utils/authentification.py Näytä tiedosto

4
 from sqlalchemy.orm.exc import NoResultFound
4
 from sqlalchemy.orm.exc import NoResultFound
5
 
5
 
6
 from tracim import TracimRequest
6
 from tracim import TracimRequest
7
+from tracim.exceptions import UserNotExist
7
 from tracim.lib.core.user import UserApi
8
 from tracim.lib.core.user import UserApi
8
 from tracim.models import User
9
 from tracim.models import User
9
 
10
 
50
         if not login:
51
         if not login:
51
             return None
52
             return None
52
         user = uapi.get_one_by_email(login)
53
         user = uapi.get_one_by_email(login)
53
-    except NoResultFound:
54
+    except (NoResultFound, UserNotExist):
54
         return None
55
         return None
55
     return user
56
     return user

+ 1 - 1
tracim/lib/utils/authorization.py Näytä tiedosto

80
             raise InsufficientUserWorkspaceRole()
80
             raise InsufficientUserWorkspaceRole()
81
 
81
 
82
         return wrapper
82
         return wrapper
83
-    return decorator
83
+    return decorator

+ 4 - 4
tracim/lib/utils/request.py Näytä tiedosto

74
             )
74
             )
75
         self._current_user = user
75
         self._current_user = user
76
 
76
 
77
-
78
 ###
77
 ###
79
 # Utils for TracimRequest
78
 # Utils for TracimRequest
80
 ###
79
 ###
112
     """
111
     """
113
     workspace_id = ''
112
     workspace_id = ''
114
     try:
113
     try:
115
-        if 'workspace_id' not in request.json_body:
116
-            raise WorkspaceNotFound('No workspace_id param in json body')
117
-        workspace_id = request.json_body['workspace_id']
114
+        if 'workspace_id' in request.matchdict:
115
+            workspace_id = request.matchdict['workspace_id']
116
+        if not workspace_id:
117
+            raise WorkspaceNotFound('No workspace_id param')
118
         wapi = WorkspaceApi(
118
         wapi = WorkspaceApi(
119
             current_user=user,
119
             current_user=user,
120
             session=request.dbsession,
120
             session=request.dbsession,

+ 21 - 8
tracim/tests/functional/test_system.py Näytä tiedosto

4
 
4
 
5
 class TestApplicationsEndpoint(FunctionalTest):
5
 class TestApplicationsEndpoint(FunctionalTest):
6
     def test_api__get_applications__ok_200__nominal_case(self):
6
     def test_api__get_applications__ok_200__nominal_case(self):
7
-        # TODO need authorization ? check permissions ?
8
-        # self.testapp.authorization = (
9
-        #     'Basic',
10
-        #     (
11
-        #         'admin@admin.admin',
12
-        #         'admin@admin.admin'
13
-        #     )
14
-        # )
7
+        self.testapp.authorization = (
8
+            'Basic',
9
+            (
10
+                'admin@admin.admin',
11
+                'admin@admin.admin'
12
+            )
13
+        )
15
         res = self.testapp.get('/api/v2/system/applications', status=200)
14
         res = self.testapp.get('/api/v2/system/applications', status=200)
16
         res = res.json_body
15
         res = res.json_body
17
         application = res[0]
16
         application = res[0]
49
         assert application['hexcolor'] == '#757575'
48
         assert application['hexcolor'] == '#757575'
50
         assert application['is_active'] is True
49
         assert application['is_active'] is True
51
         assert 'config' in application
50
         assert 'config' in application
51
+
52
+    def test_api__get_workspace__err_401__unregistered_user(self):
53
+        self.testapp.authorization = (
54
+            'Basic',
55
+            (
56
+                'john@doe.doe',
57
+                'lapin'
58
+            )
59
+        )
60
+        res = self.testapp.get('/api/v2/system/applications', status=401)
61
+        assert isinstance(res.json, dict)
62
+        assert 'code' in res.json.keys()
63
+        assert 'message' in res.json.keys()
64
+        assert 'details' in res.json.keys()

+ 30 - 33
tracim/tests/functional/test_workspaces.py Näytä tiedosto

74
         assert sidebar_entry['hexcolor'] == "#757575"
74
         assert sidebar_entry['hexcolor'] == "#757575"
75
         assert sidebar_entry['icon'] == "calendar-alt"
75
         assert sidebar_entry['icon'] == "calendar-alt"
76
 
76
 
77
-    # TODO - G.M - 22-05-2018 - Check if this feature is needed
78
-    # def test_api__get_workspace__err_403__unallowed_user(self):
79
-    #     self.testapp.authorization = (
80
-    #         'Basic',
81
-    #         (
82
-    #             'lawrence-not-real-email@fsf.local',
83
-    #             'foobarbaz'
84
-    #         )
85
-    #     )
86
-    #     res = self.testapp.get('/api/v2/workspaces/1', status=403)
87
-    #     assert isinstance(res.json, dict)
88
-    #     assert 'code' in res.json.keys()
89
-    #     assert 'message' in res.json.keys()
90
-    #     assert 'details' in res.json.keys()
77
+    def test_api__get_workspace__err_403__unallowed_user(self):
78
+        self.testapp.authorization = (
79
+            'Basic',
80
+            (
81
+                'lawrence-not-real-email@fsf.local',
82
+                'foobarbaz'
83
+            )
84
+        )
85
+        res = self.testapp.get('/api/v2/workspaces/1', status=403)
86
+        assert isinstance(res.json, dict)
87
+        assert 'code' in res.json.keys()
88
+        assert 'message' in res.json.keys()
89
+        assert 'details' in res.json.keys()
91
 
90
 
92
     def test_api__get_workspace__err_401__unregistered_user(self):
91
     def test_api__get_workspace__err_401__unregistered_user(self):
93
         self.testapp.authorization = (
92
         self.testapp.authorization = (
103
         assert 'message' in res.json.keys()
102
         assert 'message' in res.json.keys()
104
         assert 'details' in res.json.keys()
103
         assert 'details' in res.json.keys()
105
 
104
 
106
-    def test_api__get_workspace__err_404__workspace_does_not_exist(self):
105
+    def test_api__get_workspace__err_403__workspace_does_not_exist(self):
107
         self.testapp.authorization = (
106
         self.testapp.authorization = (
108
             'Basic',
107
             'Basic',
109
             (
108
             (
111
                 'admin@admin.admin'
110
                 'admin@admin.admin'
112
             )
111
             )
113
         )
112
         )
114
-        res = self.testapp.get('/api/v2/workspaces/5', status=404)
113
+        res = self.testapp.get('/api/v2/workspaces/5', status=403)
115
         assert isinstance(res.json, dict)
114
         assert isinstance(res.json, dict)
116
         assert 'code' in res.json.keys()
115
         assert 'code' in res.json.keys()
117
         assert 'message' in res.json.keys()
116
         assert 'message' in res.json.keys()
139
         assert user_role['user']['display_name'] == 'Global manager'
138
         assert user_role['user']['display_name'] == 'Global manager'
140
         assert user_role['user']['avatar_url'] is None  # TODO
139
         assert user_role['user']['avatar_url'] is None  # TODO
141
 
140
 
142
-
143
-
144
-    # def test_api__get_workspace_members__err_400__unallowed_user(self):
145
-    #     self.testapp.authorization = (
146
-    #         'Basic',
147
-    #         (
148
-    #             'lawrence-not-real-email@fsf.local',
149
-    #             'foobarbaz'
150
-    #         )
151
-    #     )
152
-    #     res = self.testapp.get('/api/v2/workspaces/3/members', status=403)
153
-    #     assert isinstance(res.json, dict)
154
-    #     assert 'code' in res.json.keys()
155
-    #     assert 'message' in res.json.keys()
156
-    #     assert 'details' in res.json.keys()
141
+    def test_api__get_workspace_members__err_403__unallowed_user(self):
142
+        self.testapp.authorization = (
143
+            'Basic',
144
+            (
145
+                'lawrence-not-real-email@fsf.local',
146
+                'foobarbaz'
147
+            )
148
+        )
149
+        res = self.testapp.get('/api/v2/workspaces/3/members', status=403)
150
+        assert isinstance(res.json, dict)
151
+        assert 'code' in res.json.keys()
152
+        assert 'message' in res.json.keys()
153
+        assert 'details' in res.json.keys()
157
 
154
 
158
     def test_api__get_workspace_members__err_401__unregistered_user(self):
155
     def test_api__get_workspace_members__err_401__unregistered_user(self):
159
         self.testapp.authorization = (
156
         self.testapp.authorization = (
169
         assert 'message' in res.json.keys()
166
         assert 'message' in res.json.keys()
170
         assert 'details' in res.json.keys()
167
         assert 'details' in res.json.keys()
171
 
168
 
172
-    def test_api__get_workspace_members__err_404__workspace_does_not_exist(self):
169
+    def test_api__get_workspace_members__err_403__workspace_does_not_exist(self):
173
         self.testapp.authorization = (
170
         self.testapp.authorization = (
174
             'Basic',
171
             'Basic',
175
             (
172
             (
177
                 'admin@admin.admin'
174
                 'admin@admin.admin'
178
             )
175
             )
179
         )
176
         )
180
-        res = self.testapp.get('/api/v2/workspaces/5/members', status=404)
177
+        res = self.testapp.get('/api/v2/workspaces/5/members', status=403)
181
         assert isinstance(res.json, dict)
178
         assert isinstance(res.json, dict)
182
         assert 'code' in res.json.keys()
179
         assert 'code' in res.json.keys()
183
         assert 'message' in res.json.keys()
180
         assert 'message' in res.json.keys()

+ 2 - 2
tracim/tests/library/test_user_api.py Näytä tiedosto

60
             session=self.session,
60
             session=self.session,
61
             config=self.config,
61
             config=self.config,
62
         )
62
         )
63
-        with pytest.raises(NoResultFound):
63
+        with pytest.raises(UserNotExist):
64
             api.get_one_by_email('unknown')
64
             api.get_one_by_email('unknown')
65
 
65
 
66
     # def test_unit__get_all__ok__nominal_case(self):
66
     # def test_unit__get_all__ok__nominal_case(self):
156
             config=self.config,
156
             config=self.config,
157
         )
157
         )
158
         with pytest.raises(AuthenticationFailed):
158
         with pytest.raises(AuthenticationFailed):
159
-            api.authenticate_user('unknown_user', 'wrong_password')
159
+            api.authenticate_user('admin@admin.admin', 'wrong_password')

+ 6 - 0
tracim/views/core_api/system_controller.py Näytä tiedosto

1
 # coding=utf-8
1
 # coding=utf-8
2
 from pyramid.config import Configurator
2
 from pyramid.config import Configurator
3
 
3
 
4
+from tracim.exceptions import NotAuthentificated, InsufficientUserProfile
5
+from tracim.lib.utils.authorization import require_profile
6
+from tracim.models import Group
4
 from tracim.models.applications import applications
7
 from tracim.models.applications import applications
5
 
8
 
6
 try:  # Python 3.5+
9
 try:  # Python 3.5+
17
 class SystemController(Controller):
20
 class SystemController(Controller):
18
 
21
 
19
     @hapic.with_api_doc()
22
     @hapic.with_api_doc()
23
+    @hapic.handle_exception(NotAuthentificated, HTTPStatus.UNAUTHORIZED)
24
+    @hapic.handle_exception(InsufficientUserProfile, HTTPStatus.FORBIDDEN)
25
+    @require_profile(Group.TIM_USER)
20
     @hapic.output_body(ApplicationSchema(many=True),)
26
     @hapic.output_body(ApplicationSchema(many=True),)
21
     def applications(self, context, request: TracimRequest, hapic_data=None):
27
     def applications(self, context, request: TracimRequest, hapic_data=None):
22
         """
28
         """

+ 6 - 10
tracim/views/core_api/user_controller.py Näytä tiedosto

30
         """
30
         """
31
         Get list of user workspaces
31
         Get list of user workspaces
32
         """
32
         """
33
-        uid = hapic_data.path['user_id']
34
         app_config = request.registry.settings['CFG']
33
         app_config = request.registry.settings['CFG']
34
+
35
+        uid = hapic_data.path['user_id']
35
         uapi = UserApi(
36
         uapi = UserApi(
36
             request.current_user,
37
             request.current_user,
37
             session=request.dbsession,
38
             session=request.dbsession,
38
             config=app_config,
39
             config=app_config,
39
         )
40
         )
41
+        user = uapi.get_one(uid)
42
+        if not uapi.can_see_private_info_of_user(user):
43
+            raise InsufficientUserProfile()
44
+
40
         wapi = WorkspaceApi(
45
         wapi = WorkspaceApi(
41
             current_user=request.current_user,  # User
46
             current_user=request.current_user,  # User
42
             session=request.dbsession,
47
             session=request.dbsession,
43
             config=app_config,
48
             config=app_config,
44
         )
49
         )
45
-        # TODO - G.M - 22-05-2018 - Refactor this in a more lib way( avoid
46
-        # try/catch and complex code here).
47
-        try:
48
-            user = uapi.get_one(uid)
49
-        except NoResultFound:
50
-            raise UserNotExist()
51
-        if not uapi.can_see_private_info_of_user(user):
52
-            raise InsufficientUserProfile()
53
-
54
         return [
50
         return [
55
             WorkspaceInContext(workspace, request.dbsession, app_config)
51
             WorkspaceInContext(workspace, request.dbsession, app_config)
56
             for workspace in wapi.get_all_for_user(user)
52
             for workspace in wapi.get_all_for_user(user)

+ 12 - 24
tracim/views/core_api/workspace_controller.py Näytä tiedosto

4
 from sqlalchemy.orm.exc import NoResultFound
4
 from sqlalchemy.orm.exc import NoResultFound
5
 
5
 
6
 from tracim.lib.core.userworkspace import RoleApi
6
 from tracim.lib.core.userworkspace import RoleApi
7
+from tracim.lib.utils.authorization import require_workspace_role
7
 from tracim.models.context_models import WorkspaceInContext, \
8
 from tracim.models.context_models import WorkspaceInContext, \
8
     UserRoleWorkspaceInContext
9
     UserRoleWorkspaceInContext
10
+from tracim.models.data import UserRoleInWorkspace
9
 
11
 
10
 try:  # Python 3.5+
12
 try:  # Python 3.5+
11
     from http import HTTPStatus
13
     from http import HTTPStatus
25
 class WorkspaceController(Controller):
27
 class WorkspaceController(Controller):
26
 
28
 
27
     @hapic.with_api_doc()
29
     @hapic.with_api_doc()
28
-    @hapic.input_path(WorkspaceIdPathSchema())
29
     @hapic.handle_exception(NotAuthentificated, HTTPStatus.UNAUTHORIZED)
30
     @hapic.handle_exception(NotAuthentificated, HTTPStatus.UNAUTHORIZED)
30
-    #@hapic.handle_exception(InsufficientUserProfile, HTTPStatus.FORBIDDEN)
31
-    @hapic.handle_exception(WorkspaceNotFound, HTTPStatus.NOT_FOUND)
31
+    @hapic.handle_exception(InsufficientUserProfile, HTTPStatus.FORBIDDEN)
32
+    @hapic.handle_exception(WorkspaceNotFound, HTTPStatus.FORBIDDEN)
33
+    @require_workspace_role(UserRoleInWorkspace.READER)
34
+    @hapic.input_path(WorkspaceIdPathSchema())
32
     @hapic.output_body(WorkspaceSchema())
35
     @hapic.output_body(WorkspaceSchema())
33
     def workspace(self, context, request: TracimRequest, hapic_data=None):
36
     def workspace(self, context, request: TracimRequest, hapic_data=None):
34
         """
37
         """
41
             session=request.dbsession,
44
             session=request.dbsession,
42
             config=app_config,
45
             config=app_config,
43
         )
46
         )
44
-        # TODO - G.M - 22-05-2018 - Refactor this in a more lib way( avoid
45
-        # try/catch and complex code here).
46
-        try:
47
-            workspace = wapi.get_one(wid)
48
-        except NoResultFound:
49
-            raise WorkspaceNotFound()
50
-        return wapi.get_workspace_with_context(workspace)
47
+        return wapi.get_workspace_with_context(request.current_workspace)
51
 
48
 
52
     @hapic.with_api_doc()
49
     @hapic.with_api_doc()
53
-    @hapic.input_path(WorkspaceIdPathSchema())
54
     @hapic.handle_exception(NotAuthentificated, HTTPStatus.UNAUTHORIZED)
50
     @hapic.handle_exception(NotAuthentificated, HTTPStatus.UNAUTHORIZED)
55
-    #@hapic.handle_exception(InsufficientUserProfile, HTTPStatus.FORBIDDEN)
56
-    @hapic.handle_exception(WorkspaceNotFound, HTTPStatus.NOT_FOUND)
51
+    @hapic.handle_exception(InsufficientUserProfile, HTTPStatus.FORBIDDEN)
52
+    @hapic.handle_exception(WorkspaceNotFound, HTTPStatus.FORBIDDEN)
53
+    @require_workspace_role(UserRoleInWorkspace.READER)
54
+    @hapic.input_path(WorkspaceIdPathSchema())
57
     @hapic.output_body(WorkspaceMemberSchema(many=True))
55
     @hapic.output_body(WorkspaceMemberSchema(many=True))
58
     def workspaces_members(
56
     def workspaces_members(
59
             self,
57
             self,
64
         """
62
         """
65
         Get Members of this workspace
63
         Get Members of this workspace
66
         """
64
         """
67
-        wid = hapic_data.path['workspace_id']
68
         app_config = request.registry.settings['CFG']
65
         app_config = request.registry.settings['CFG']
69
         rapi = RoleApi(
66
         rapi = RoleApi(
70
             current_user=request.current_user,
67
             current_user=request.current_user,
71
             session=request.dbsession,
68
             session=request.dbsession,
72
             config=app_config,
69
             config=app_config,
73
         )
70
         )
74
-        wapi = WorkspaceApi(
75
-            current_user=request.current_user,
76
-            session=request.dbsession,
77
-            config=app_config,
78
-        )
79
-        try:
80
-            wapi.get_one(wid)
81
-        except NoResultFound:
82
-            raise WorkspaceNotFound()
83
         return [
71
         return [
84
             rapi.get_user_role_workspace_with_context(user_role)
72
             rapi.get_user_role_workspace_with_context(user_role)
85
-            for user_role in rapi.get_all_for_workspace(wid)
73
+            for user_role in rapi.get_all_for_workspace(request.current_workspace)
86
         ]
74
         ]
87
 
75
 
88
     def bind(self, configurator: Configurator) -> None:
76
     def bind(self, configurator: Configurator) -> None: