浏览代码

Add workspace endpoint + some fixes

Guénaël Muller 7 年前
父节点
当前提交
c6ad857f45

+ 9 - 6
tracim/__init__.py 查看文件

17
 from tracim.views.core_api.session_controller import SessionController
17
 from tracim.views.core_api.session_controller import SessionController
18
 from tracim.views.core_api.system_controller import SystemController
18
 from tracim.views.core_api.system_controller import SystemController
19
 from tracim.views.core_api.user_controller import UserController
19
 from tracim.views.core_api.user_controller import UserController
20
+from tracim.views.core_api.workspace_controller import WorkspaceController
20
 from tracim.views.errors import ErrorSchema
21
 from tracim.views.errors import ErrorSchema
21
 from tracim.lib.utils.cors import add_cors_support
22
 from tracim.lib.utils.cors import add_cors_support
22
 
23
 
58
         )
59
         )
59
     )
60
     )
60
     # Add controllers
61
     # Add controllers
61
-    session_api = SessionController()
62
-    system_api = SystemController()
63
-    user_api = UserController()
64
-    configurator.include(session_api.bind, route_prefix=BASE_API_V2)
65
-    configurator.include(system_api.bind, route_prefix=BASE_API_V2)
66
-    configurator.include(user_api.bind, route_prefix=BASE_API_V2)
62
+    session_controller = SessionController()
63
+    system_controller = SystemController()
64
+    user_controller = UserController()
65
+    workspace_controller = WorkspaceController()
66
+    configurator.include(session_controller.bind, route_prefix=BASE_API_V2)
67
+    configurator.include(system_controller.bind, route_prefix=BASE_API_V2)
68
+    configurator.include(user_controller.bind, route_prefix=BASE_API_V2)
69
+    configurator.include(workspace_controller.bind, route_prefix=BASE_API_V2)
67
     hapic.add_documentation_view(
70
     hapic.add_documentation_view(
68
         '/api/v2/doc',
71
         '/api/v2/doc',
69
         'Tracim v2 API',
72
         'Tracim v2 API',

+ 1 - 1
tracim/lib/core/userworkspace.py 查看文件

4
 __author__ = 'damien'
4
 __author__ = 'damien'
5
 
5
 
6
 from sqlalchemy.orm import Session
6
 from sqlalchemy.orm import Session
7
-from tracim.models.auth import User
7
+from tracim.models.auth import User, Group
8
 from tracim.models.data import Workspace
8
 from tracim.models.data import Workspace
9
 from tracim.models.data import UserRoleInWorkspace
9
 from tracim.models.data import UserRoleInWorkspace
10
 from tracim.models.data import RoleType
10
 from tracim.models.data import RoleType

+ 70 - 1
tracim/models/context_models.py 查看文件

7
 from tracim import CFG
7
 from tracim import CFG
8
 from tracim.models import User
8
 from tracim.models import User
9
 from tracim.models.auth import Profile
9
 from tracim.models.auth import Profile
10
-from tracim.models.data import Workspace
10
+from tracim.models.data import Workspace, UserRoleInWorkspace
11
 from tracim.models.workspace_menu_entries import default_workspace_menu_entry, \
11
 from tracim.models.workspace_menu_entries import default_workspace_menu_entry, \
12
     WorkspaceMenuEntry
12
     WorkspaceMenuEntry
13
 
13
 
135
         # list should be able to change (depending on activated/disabled
135
         # list should be able to change (depending on activated/disabled
136
         # apps)
136
         # apps)
137
         return default_workspace_menu_entry(self.workspace)
137
         return default_workspace_menu_entry(self.workspace)
138
+
139
+
140
+class UserRoleWorkspaceInContext(object):
141
+    """
142
+    Interface to get UserRoleInWorkspace data and related content
143
+
144
+    """
145
+    def __init__(
146
+            self,
147
+            user_role: UserRoleInWorkspace,
148
+            dbsession: Session,
149
+            config: CFG,
150
+    )-> None:
151
+        self.user_role = user_role
152
+        self.dbsession = dbsession
153
+        self.config = config
154
+
155
+    @property
156
+    def user_id(self) -> int:
157
+        """
158
+        User who has the role has this id
159
+        :return: user id as integer
160
+        """
161
+        return self.user_role.user_id
162
+
163
+    @property
164
+    def workspace_id(self) -> int:
165
+        """
166
+        This role apply only on the workspace with this workspace_id
167
+        :return: workspace id as integer
168
+        """
169
+        return self.user_role.workspace_id
170
+
171
+    # TODO - G.M - 23-05-2018 - Check the API spec for this this !
172
+
173
+    @property
174
+    def slug(self) -> str:
175
+        """
176
+        simple name of the role of the user.
177
+        can be anything from UserRoleInWorkspace SLUG, like
178
+        'not_applicable', 'reader',
179
+        'contributor', 'content_manager', 'workspace_manager'
180
+        :return: user workspace role as slug.
181
+        """
182
+        return UserRoleInWorkspace.SLUG[self.user_role.role]
183
+
184
+    @property
185
+    def user(self) -> UserInContext:
186
+        """
187
+        User who has this role, with context data
188
+        :return: UserInContext object
189
+        """
190
+        return UserInContext(
191
+            self.user_role.user,
192
+            self.dbsession,
193
+            self.config
194
+        )
195
+
196
+    @property
197
+    def workspace(self) -> WorkspaceInContext:
198
+        """
199
+        Workspace related to this role, with his context data
200
+        :return: WorkspaceInContext object
201
+        """
202
+        return WorkspaceInContext(
203
+            self.user_role.workspace,
204
+            self.dbsession,
205
+            self.config
206
+        )

+ 6 - 0
tracim/models/data.py 查看文件

131
     WORKSPACE_MANAGER = 8
131
     WORKSPACE_MANAGER = 8
132
 
132
 
133
     # TODO - G.M - 10-04-2018 - [Cleanup] Drop this
133
     # TODO - G.M - 10-04-2018 - [Cleanup] Drop this
134
+    SLUG = dict()
135
+    SLUG[NOT_APPLICABLE] = 'not_applicable'
136
+    SLUG[READER] = 'reader'
137
+    SLUG[CONTRIBUTOR] = 'contributor'
138
+    SLUG[CONTENT_MANAGER] = 'content_manager'
139
+    SLUG[WORKSPACE_MANAGER] = 'workspace_manager'
134
     # LABEL = dict()
140
     # LABEL = dict()
135
     # LABEL[0] = l_('N/A')
141
     # LABEL[0] = l_('N/A')
136
     # LABEL[1] = l_('Reader')
142
     # LABEL[1] = l_('Reader')

+ 0 - 2
tracim/tests/functional/test_user.py 查看文件

20
         res = res.json_body
20
         res = res.json_body
21
         workspace = res[0]
21
         workspace = res[0]
22
         assert workspace['id'] == 1
22
         assert workspace['id'] == 1
23
-        assert workspace['slug'] == 'w1'
24
         assert workspace['label'] == 'w1'
23
         assert workspace['label'] == 'w1'
25
-        assert workspace['description'] == 'This is a workspace'
26
         assert len(workspace['sidebar_entries']) == 7  # TODO change this
24
         assert len(workspace['sidebar_entries']) == 7  # TODO change this
27
 
25
 
28
         sidebar_entry = workspace['sidebar_entries'][0]
26
         sidebar_entry = workspace['sidebar_entries'][0]

+ 97 - 60
tracim/tests/functional/test_workspaces.py 查看文件

1
 # coding=utf-8
1
 # coding=utf-8
2
-
2
+from tracim.models.data import UserRoleInWorkspace
3
 from tracim.tests import FunctionalTest
3
 from tracim.tests import FunctionalTest
4
+from tracim.fixtures.content import Content as ContentFixtures
5
+from tracim.fixtures.users_and_groups import Base as BaseFixture
4
 
6
 
5
 
7
 
6
 class TestWorkspaceEndpoint(FunctionalTest):
8
 class TestWorkspaceEndpoint(FunctionalTest):
7
 
9
 
10
+    fixtures = [BaseFixture, ContentFixtures]
11
+
8
     def test_api__get_workspace__ok_200__nominal_case(self):
12
     def test_api__get_workspace__ok_200__nominal_case(self):
9
         self.testapp.authorization = (
13
         self.testapp.authorization = (
10
             'Basic',
14
             'Basic',
13
                 'admin@admin.admin'
17
                 'admin@admin.admin'
14
             )
18
             )
15
         )
19
         )
16
-        workspace = self.testapp.post_json('/api/v2/workspaces/1', status=200)
20
+        res = self.testapp.get('/api/v2/workspaces/1', status=200)
21
+        workspace = res.json_body
17
         assert workspace['id'] == 1
22
         assert workspace['id'] == 1
18
         assert workspace['slug'] == 'w1'
23
         assert workspace['slug'] == 'w1'
19
         assert workspace['label'] == 'w1'
24
         assert workspace['label'] == 'w1'
20
-        assert workspace['description'] == 'Just another description'
21
-        assert len(workspace['sidebar_entries']) == 3  # TODO change this
25
+        assert workspace['description'] == 'This is a workspace'
26
+        assert len(workspace['sidebar_entries']) == 7  # TODO change this
22
 
27
 
23
         sidebar_entry = workspace['sidebar_entries'][0]
28
         sidebar_entry = workspace['sidebar_entries'][0]
24
-        assert sidebar_entry['slug'] == 'markdown-pages'
25
-        assert sidebar_entry['label'] == 'Document Markdown'
26
-        assert sidebar_entry['route'] == "/#/workspace/{workspace_id}/contents/?type=mardown-page"  # nopep8
27
-        assert sidebar_entry['hexcolor'] == "#F0F9DC"
29
+        assert sidebar_entry['slug'] == 'dashboard'
30
+        assert sidebar_entry['label'] == 'Dashboard'
31
+        assert sidebar_entry['route'] == '/#/workspaces/1/dashboard'  # nopep8
32
+        assert sidebar_entry['hexcolor'] == "#252525"
33
+        assert sidebar_entry['icon'] == ""
34
+
35
+        sidebar_entry = workspace['sidebar_entries'][1]
36
+        assert sidebar_entry['slug'] == 'contents/all'
37
+        assert sidebar_entry['label'] == 'All Contents'
38
+        assert sidebar_entry['route'] == "/#/workspaces/1/contents"  # nopep8
39
+        assert sidebar_entry['hexcolor'] == "#fdfdfd"
40
+        assert sidebar_entry['icon'] == ""
41
+
42
+        sidebar_entry = workspace['sidebar_entries'][2]
43
+        assert sidebar_entry['slug'] == 'contents/pagehtml'
44
+        assert sidebar_entry['label'] == 'Text Documents'
45
+        assert sidebar_entry['route'] == '/#/workspaces/1/contents?type=pagehtml'  # nopep8
46
+        assert sidebar_entry['hexcolor'] == "#3f52e3"
28
         assert sidebar_entry['icon'] == "file-text-o"
47
         assert sidebar_entry['icon'] == "file-text-o"
29
-        # TODO To this for the other
30
 
48
 
31
-    def test_api__get_workspace__err_403__unallowed_user(self):
32
-        self.testapp.authorization = (
33
-            'Basic',
34
-            (
35
-                'lawrence-not-real-email@fsf.local',
36
-                'foobarbaz'
37
-            )
38
-        )
39
-        res = self.testapp.post_json('/api/v2/workspaces/1', status=403)
40
-        assert isinstance(res.json, dict)
41
-        assert 'code' in res.json.keys()
42
-        assert 'message' in res.json.keys()
43
-        assert 'details' in res.json.keys()
49
+        sidebar_entry = workspace['sidebar_entries'][3]
50
+        assert sidebar_entry['slug'] == 'contents/pagemarkdownplus'
51
+        assert sidebar_entry['label'] == 'Rich Markdown Files'
52
+        assert sidebar_entry['route'] == "/#/workspaces/1/contents?type=pagemarkdownplus"    # nopep8
53
+        assert sidebar_entry['hexcolor'] == "#f12d2d"
54
+        assert sidebar_entry['icon'] == "file-code"
55
+
56
+        sidebar_entry = workspace['sidebar_entries'][4]
57
+        assert sidebar_entry['slug'] == 'contents/files'
58
+        assert sidebar_entry['label'] == 'Files'
59
+        assert sidebar_entry['route'] == "/#/workspaces/1/contents?type=file"  # nopep8
60
+        assert sidebar_entry['hexcolor'] == "#FF9900"
61
+        assert sidebar_entry['icon'] == "paperclip"
62
+
63
+        sidebar_entry = workspace['sidebar_entries'][5]
64
+        assert sidebar_entry['slug'] == 'contents/threads'
65
+        assert sidebar_entry['label'] == 'Threads'
66
+        assert sidebar_entry['route'] == "/#/workspaces/1/contents?type=thread"  # nopep8
67
+        assert sidebar_entry['hexcolor'] == "#ad4cf9"
68
+        assert sidebar_entry['icon'] == "comments-o"
69
+
70
+        sidebar_entry = workspace['sidebar_entries'][6]
71
+        assert sidebar_entry['slug'] == 'calendar'
72
+        assert sidebar_entry['label'] == 'Calendar'
73
+        assert sidebar_entry['route'] == "/#/workspaces/1/calendar"  # nopep8
74
+        assert sidebar_entry['hexcolor'] == "#757575"
75
+        assert sidebar_entry['icon'] == "calendar-alt"
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()
44
 
91
 
45
     def test_api__get_workspace__err_401__unregistered_user(self):
92
     def test_api__get_workspace__err_401__unregistered_user(self):
46
         self.testapp.authorization = (
93
         self.testapp.authorization = (
50
                 'lapin'
97
                 'lapin'
51
             )
98
             )
52
         )
99
         )
53
-        res = self.testapp.post_json('/api/v2/workspaces/1', status=401)
100
+        res = self.testapp.get('/api/v2/workspaces/1', status=401)
54
         assert isinstance(res.json, dict)
101
         assert isinstance(res.json, dict)
55
         assert 'code' in res.json.keys()
102
         assert 'code' in res.json.keys()
56
         assert 'message' in res.json.keys()
103
         assert 'message' in res.json.keys()
64
                 'admin@admin.admin'
111
                 'admin@admin.admin'
65
             )
112
             )
66
         )
113
         )
67
-        res = self.testapp.post_json('/api/v2/workspaces/5', status=404)
114
+        res = self.testapp.get('/api/v2/workspaces/5', status=404)
68
         assert isinstance(res.json, dict)
115
         assert isinstance(res.json, dict)
69
         assert 'code' in res.json.keys()
116
         assert 'code' in res.json.keys()
70
         assert 'message' in res.json.keys()
117
         assert 'message' in res.json.keys()
73
 
120
 
74
 class TestWorkspaceMembersEndpoint(FunctionalTest):
121
 class TestWorkspaceMembersEndpoint(FunctionalTest):
75
 
122
 
123
+    fixtures = [BaseFixture, ContentFixtures]
124
+
76
     def test_api__get_workspace_members__ok_200__nominal_case(self):
125
     def test_api__get_workspace_members__ok_200__nominal_case(self):
77
         self.testapp.authorization = (
126
         self.testapp.authorization = (
78
             'Basic',
127
             'Basic',
81
                 'admin@admin.admin'
130
                 'admin@admin.admin'
82
             )
131
             )
83
         )
132
         )
84
-        res = self.testapp.post_json('/api/v2/workspaces/1/members', status=200)
133
+        res = self.testapp.get('/api/v2/workspaces/1/members', status=200).json_body
85
         assert len(res) == 2
134
         assert len(res) == 2
86
         user_role = res[0]
135
         user_role = res[0]
87
-        assert user_role['role'] == 'administrator'
88
-        assert user_role['user_id'] == '1'
89
-        assert user_role['workspace_id'] == '1'
90
-        assert user_role['user']['label'] == 'Global manager'
91
-        assert user_role['user']['avatar_url'] == ''  # TODO
92
-
93
-        assert res['role'] == 1
94
-        assert res['slug'] == 'w1'
95
-        assert res['label'] == 'w1'
96
-        assert res['description'] == 'Just another description'
97
-        assert len(res['sidebar_entries']) == 3  # TODO change this
98
-
99
-        sidebar_entry = res['sidebar_entries'][0]
100
-        assert sidebar_entry['slug'] == 'markdown-pages'
101
-        assert sidebar_entry['label'] == 'Document Markdown'
102
-        assert sidebar_entry['route'] == "/#/workspace/{workspace_id}/contents/?type=mardown-page"  # nopep8
103
-        assert sidebar_entry['hexcolor'] == "#F0F9DC"
104
-        assert sidebar_entry['icon'] == "file-text-o"
105
-        # TODO Do this for the other
106
-
107
-    def test_api__get_workspace_members__err_400__unallowed_user(self):
108
-        self.testapp.authorization = (
109
-            'Basic',
110
-            (
111
-                'lawrence-not-real-email@fsf.local',
112
-                'foobarbaz'
113
-            )
114
-        )
115
-        res = self.testapp.post_json('/api/v2/workspaces/1/members', status=403)
116
-        assert isinstance(res.json, dict)
117
-        assert 'code' in res.json.keys()
118
-        assert 'message' in res.json.keys()
119
-        assert 'details' in res.json.keys()
136
+        assert user_role['slug'] == 'workspace_manager'
137
+        assert user_role['user_id'] == 1
138
+        assert user_role['workspace_id'] == 1
139
+        assert user_role['user']['display_name'] == 'Global manager'
140
+        assert user_role['user']['avatar_url'] is None  # TODO
141
+
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()
120
 
157
 
121
     def test_api__get_workspace_members__err_401__unregistered_user(self):
158
     def test_api__get_workspace_members__err_401__unregistered_user(self):
122
         self.testapp.authorization = (
159
         self.testapp.authorization = (
126
                 'lapin'
163
                 'lapin'
127
             )
164
             )
128
         )
165
         )
129
-        res = self.testapp.post_json('/api/v2/workspaces/1/members', status=403)
166
+        res = self.testapp.get('/api/v2/workspaces/1/members', status=401)
130
         assert isinstance(res.json, dict)
167
         assert isinstance(res.json, dict)
131
         assert 'code' in res.json.keys()
168
         assert 'code' in res.json.keys()
132
         assert 'message' in res.json.keys()
169
         assert 'message' in res.json.keys()
140
                 'admin@admin.admin'
177
                 'admin@admin.admin'
141
             )
178
             )
142
         )
179
         )
143
-        res = self.testapp.post_json('/api/v2/workspaces/5/members', status=404)
180
+        res = self.testapp.get('/api/v2/workspaces/5/members', status=404)
144
         assert isinstance(res.json, dict)
181
         assert isinstance(res.json, dict)
145
         assert 'code' in res.json.keys()
182
         assert 'code' in res.json.keys()
146
         assert 'message' in res.json.keys()
183
         assert 'message' in res.json.keys()

+ 9 - 2
tracim/views/core_api/schemas.py 查看文件

36
     user_id = marshmallow.fields.Int()
36
     user_id = marshmallow.fields.Int()
37
 
37
 
38
 
38
 
39
+class WorkspaceIdPathSchema(marshmallow.Schema):
40
+    workspace_id = marshmallow.fields.Int()
41
+
42
+
39
 class BasicAuthSchema(marshmallow.Schema):
43
 class BasicAuthSchema(marshmallow.Schema):
40
 
44
 
41
     email = marshmallow.fields.Email(required=True)
45
     email = marshmallow.fields.Email(required=True)
72
         many=True,
76
         many=True,
73
     )
77
     )
74
 
78
 
79
+
75
 class WorkspaceDigestSchema(marshmallow.Schema):
80
 class WorkspaceDigestSchema(marshmallow.Schema):
76
     id = marshmallow.fields.Int()
81
     id = marshmallow.fields.Int()
77
     label = marshmallow.fields.String()
82
     label = marshmallow.fields.String()
82
 
87
 
83
 
88
 
84
 class WorkspaceMemberSchema(marshmallow.Schema):
89
 class WorkspaceMemberSchema(marshmallow.Schema):
85
-    role = marshmallow.fields.String()
90
+    slug = marshmallow.fields.String()
86
     user_id = marshmallow.fields.Int()
91
     user_id = marshmallow.fields.Int()
87
     workspace_id = marshmallow.fields.Int()
92
     workspace_id = marshmallow.fields.Int()
88
-    # TODO user
93
+    user = marshmallow.fields.Nested(
94
+        UserSchema(only=('display_name', 'avatar_url'))
95
+    )
89
 
96
 
90
 
97
 
91
 class ApplicationConfigSchema(marshmallow.Schema):
98
 class ApplicationConfigSchema(marshmallow.Schema):

+ 8 - 10
tracim/views/core_api/user_controller.py 查看文件

14
 from tracim.lib.core.user import UserApi
14
 from tracim.lib.core.user import UserApi
15
 from tracim.lib.core.workspace import WorkspaceApi
15
 from tracim.lib.core.workspace import WorkspaceApi
16
 from tracim.views.controllers import Controller
16
 from tracim.views.controllers import Controller
17
-from tracim.views.core_api.schemas import WorkspaceSchema, UserSchema, \
18
-    UserIdPathSchema
17
+from tracim.views.core_api.schemas import UserIdPathSchema, \
18
+    WorkspaceDigestSchema
19
 
19
 
20
 
20
 
21
 class UserController(Controller):
21
 class UserController(Controller):
25
     @hapic.handle_exception(NotAuthentificated, HTTPStatus.UNAUTHORIZED)
25
     @hapic.handle_exception(NotAuthentificated, HTTPStatus.UNAUTHORIZED)
26
     @hapic.handle_exception(InsufficientUserProfile, HTTPStatus.FORBIDDEN)
26
     @hapic.handle_exception(InsufficientUserProfile, HTTPStatus.FORBIDDEN)
27
     @hapic.handle_exception(UserNotExist, HTTPStatus.NOT_FOUND)
27
     @hapic.handle_exception(UserNotExist, HTTPStatus.NOT_FOUND)
28
-    @hapic.output_body(WorkspaceSchema(many=True),)
28
+    @hapic.output_body(WorkspaceDigestSchema(many=True),)
29
     def user_workspace(self, context, request: TracimRequest, hapic_data=None):
29
     def user_workspace(self, context, request: TracimRequest, hapic_data=None):
30
         """
30
         """
31
         Get list of user workspaces
31
         Get list of user workspaces
49
             raise UserNotExist()
49
             raise UserNotExist()
50
         if not uapi.can_see_private_info_of_user(user):
50
         if not uapi.can_see_private_info_of_user(user):
51
             raise InsufficientUserProfile()
51
             raise InsufficientUserProfile()
52
-        workspaces = wapi.get_all_for_user(user)
53
-        workspaces_in_context = []
54
-        for workspace in workspaces:
55
-            workspaces_in_context.append(
56
-                WorkspaceInContext(workspace, request.dbsession, app_config)
57
-            )
58
-        return workspaces_in_context
52
+
53
+        return [
54
+            WorkspaceInContext(workspace, request.dbsession, app_config)
55
+            for workspace in wapi.get_all_for_user(user)
56
+        ]
59
 
57
 
60
     def bind(self, configurator: Configurator) -> None:
58
     def bind(self, configurator: Configurator) -> None:
61
         """
59
         """

+ 94 - 0
tracim/views/core_api/workspace_controller.py 查看文件

1
+from pyramid.config import Configurator
2
+from sqlalchemy.orm.exc import NoResultFound
3
+
4
+from tracim.lib.core.userworkspace import RoleApi
5
+from tracim.models.context_models import WorkspaceInContext, \
6
+    UserRoleWorkspaceInContext
7
+
8
+try:  # Python 3.5+
9
+    from http import HTTPStatus
10
+except ImportError:
11
+    from http import client as HTTPStatus
12
+
13
+from tracim import hapic, TracimRequest
14
+from tracim.exceptions import NotAuthentificated, InsufficientUserProfile, \
15
+    WorkspaceNotFound
16
+from tracim.lib.core.user import UserApi
17
+from tracim.lib.core.workspace import WorkspaceApi
18
+from tracim.views.controllers import Controller
19
+from tracim.views.core_api.schemas import WorkspaceSchema, UserSchema, \
20
+    WorkspaceIdPathSchema, WorkspaceMemberSchema
21
+
22
+
23
+class WorkspaceController(Controller):
24
+
25
+    @hapic.with_api_doc()
26
+    @hapic.input_path(WorkspaceIdPathSchema())
27
+    @hapic.handle_exception(NotAuthentificated, HTTPStatus.UNAUTHORIZED)
28
+    #@hapic.handle_exception(InsufficientUserProfile, HTTPStatus.FORBIDDEN)
29
+    @hapic.handle_exception(WorkspaceNotFound, HTTPStatus.NOT_FOUND)
30
+    @hapic.output_body(WorkspaceSchema())
31
+    def workspace(self, context, request: TracimRequest, hapic_data=None):
32
+        """
33
+        Get workspace information
34
+        """
35
+        wid = hapic_data.path['workspace_id']
36
+        app_config = request.registry.settings['CFG']
37
+        wapi = WorkspaceApi(
38
+            current_user=request.current_user,  # User
39
+            session=request.dbsession,
40
+        )
41
+        # TODO - G.M - 22-05-2018 - Refactor this in a more lib way( avoid
42
+        # try/catch and complex code here).
43
+        try:
44
+            workspace = wapi.get_one(wid)
45
+        except NoResultFound:
46
+            raise WorkspaceNotFound()
47
+        return WorkspaceInContext(workspace, request.dbsession, app_config)
48
+
49
+    @hapic.with_api_doc()
50
+    @hapic.input_path(WorkspaceIdPathSchema())
51
+    @hapic.handle_exception(NotAuthentificated, HTTPStatus.UNAUTHORIZED)
52
+    #@hapic.handle_exception(InsufficientUserProfile, HTTPStatus.FORBIDDEN)
53
+    @hapic.handle_exception(WorkspaceNotFound, HTTPStatus.NOT_FOUND)
54
+    @hapic.output_body(WorkspaceMemberSchema(many=True))
55
+    def workspaces_members(
56
+            self,
57
+            context,
58
+            request: TracimRequest,
59
+            hapic_data=None
60
+    ) -> None:
61
+        wid = hapic_data.path['workspace_id']
62
+        app_config = request.registry.settings['CFG']
63
+        rapi = RoleApi(
64
+            current_user=request.current_user,
65
+            session=request.dbsession,
66
+        )
67
+        wapi = WorkspaceApi(
68
+            current_user=request.current_user,
69
+            session=request.dbsession,
70
+        )
71
+        try:
72
+            wapi.get_one(wid)
73
+        except NoResultFound:
74
+            raise WorkspaceNotFound()
75
+        return [
76
+            UserRoleWorkspaceInContext(
77
+                user_role,
78
+                request.dbsession,
79
+                app_config
80
+            )
81
+            for user_role in rapi.get_all_for_workspace(wid)
82
+        ]
83
+
84
+    def bind(self, configurator: Configurator) -> None:
85
+        """
86
+        Create all routes and views using pyramid configurator
87
+        for this controller
88
+        """
89
+
90
+        # Applications
91
+        configurator.add_route('workspace', '/workspaces/{workspace_id}', request_method='GET')  # nopep8
92
+        configurator.add_view(self.workspace, route_name='workspace')
93
+        configurator.add_route('workspace_members', '/workspaces/{workspace_id}/members', request_method='GET')  # nopep8
94
+        configurator.add_view(self.workspaces_members, route_name='workspace_members')