Ver código fonte

Merge branch 'feature/578_add_api_for_workspace/apps' of github.com:tracim/tracim_backend into fix/few_more_tests

Guénaël Muller 6 anos atrás
pai
commit
fee8ec3a45

+ 1 - 0
setup.py Ver arquivo

39
     'lxml',
39
     'lxml',
40
     'redis',
40
     'redis',
41
     'rq',
41
     'rq',
42
+    'python-slugify',
42
 ]
43
 ]
43
 
44
 
44
 tests_require = [
45
 tests_require = [

+ 11 - 2
tracim/__init__.py Ver arquivo

18
 from tracim.lib.webdav import WebdavAppFactory
18
 from tracim.lib.webdav import WebdavAppFactory
19
 from tracim.views import BASE_API_V2
19
 from tracim.views import BASE_API_V2
20
 from tracim.views.core_api.session_controller import SessionController
20
 from tracim.views.core_api.session_controller import SessionController
21
+from tracim.views.core_api.system_controller import SystemController
22
+from tracim.views.core_api.user_controller import UserController
23
+from tracim.views.core_api.workspace_controller import WorkspaceController
21
 from tracim.views.errors import ErrorSchema
24
 from tracim.views.errors import ErrorSchema
22
 from tracim.lib.utils.cors import add_cors_support
25
 from tracim.lib.utils.cors import add_cors_support
23
 
26
 
62
     context.handle_exception(NotFound, 404)
65
     context.handle_exception(NotFound, 404)
63
     context.handle_exception(OperationalError, 500)
66
     context.handle_exception(OperationalError, 500)
64
     # Add controllers
67
     # Add controllers
65
-    session_api = SessionController()
66
-    configurator.include(session_api.bind, route_prefix=BASE_API_V2)
68
+    session_controller = SessionController()
69
+    system_controller = SystemController()
70
+    user_controller = UserController()
71
+    workspace_controller = WorkspaceController()
72
+    configurator.include(session_controller.bind, route_prefix=BASE_API_V2)
73
+    configurator.include(system_controller.bind, route_prefix=BASE_API_V2)
74
+    configurator.include(user_controller.bind, route_prefix=BASE_API_V2)
75
+    configurator.include(workspace_controller.bind, route_prefix=BASE_API_V2)
67
     hapic.add_documentation_view(
76
     hapic.add_documentation_view(
68
         '/api/v2/doc',
77
         '/api/v2/doc',
69
         'Tracim v2 API',
78
         'Tracim v2 API',

+ 1 - 0
tracim/command/user.py Ver arquivo

175
         self._group_api = GroupApi(
175
         self._group_api = GroupApi(
176
             current_user=None,
176
             current_user=None,
177
             session=self._session,
177
             session=self._session,
178
+            config=self._app_config,
178
         )
179
         )
179
         user = self._proceed_user(parsed_args)
180
         user = self._proceed_user(parsed_args)
180
         self._proceed_groups(user, parsed_args)
181
         self._proceed_groups(user, parsed_args)

+ 18 - 3
tracim/fixtures/content.py Ver arquivo

24
         admin_workspace_api = WorkspaceApi(
24
         admin_workspace_api = WorkspaceApi(
25
             current_user=admin,
25
             current_user=admin,
26
             session=self._session,
26
             session=self._session,
27
+            config=self._config,
27
         )
28
         )
28
         bob_workspace_api = WorkspaceApi(
29
         bob_workspace_api = WorkspaceApi(
29
             current_user=bob,
30
             current_user=bob,
30
             session=self._session,
31
             session=self._session,
32
+            config=self._config
31
         )
33
         )
32
         content_api = ContentApi(
34
         content_api = ContentApi(
33
             current_user=admin,
35
             current_user=admin,
37
         role_api = RoleApi(
39
         role_api = RoleApi(
38
             current_user=admin,
40
             current_user=admin,
39
             session=self._session,
41
             session=self._session,
42
+            config=self._config,
40
         )
43
         )
41
 
44
 
42
         # Workspaces
45
         # Workspaces
43
-        w1 = admin_workspace_api.create_workspace('w1', save_now=True)
44
-        w2 = bob_workspace_api.create_workspace('w2', save_now=True)
45
-        w3 = admin_workspace_api.create_workspace('w3', save_now=True)
46
+        w1 = admin_workspace_api.create_workspace(
47
+            'w1',
48
+            description='This is a workspace',
49
+            save_now=True
50
+        )
51
+        w2 = bob_workspace_api.create_workspace(
52
+            'w2',
53
+            description='A great workspace',
54
+            save_now=True
55
+        )
56
+        w3 = admin_workspace_api.create_workspace(
57
+            'w3',
58
+            description='Just another workspace',
59
+            save_now=True
60
+        )
46
 
61
 
47
         # Workspaces roles
62
         # Workspaces roles
48
         role_api.create_one(
63
         role_api.create_one(

+ 5 - 0
tracim/lib/core/group.py Ver arquivo

4
 from sqlalchemy.orm.exc import NoResultFound
4
 from sqlalchemy.orm.exc import NoResultFound
5
 
5
 
6
 from tracim.exceptions import GroupNotExist
6
 from tracim.exceptions import GroupNotExist
7
+from tracim import CFG
8
+
7
 
9
 
8
 __author__ = 'damien'
10
 __author__ = 'damien'
9
 
11
 
18
             self,
20
             self,
19
             session: Session,
21
             session: Session,
20
             current_user: typing.Optional[User],
22
             current_user: typing.Optional[User],
23
+            config: CFG
24
+
21
     ):
25
     ):
22
         self._user = current_user
26
         self._user = current_user
23
         self._session = session
27
         self._session = session
28
+        self._config = config
24
 
29
 
25
     def _base_query(self) -> Query:
30
     def _base_query(self) -> Query:
26
         return self._session.query(Group)
31
         return self._session.query(Group)

+ 12 - 4
tracim/lib/core/user.py Ver arquivo

10
 from sqlalchemy.orm import Session
10
 from sqlalchemy.orm import Session
11
 
11
 
12
 from tracim import CFG
12
 from tracim import CFG
13
-from tracim.models.auth import User
13
+from tracim.models.auth import User, Group
14
 from sqlalchemy.orm.exc import NoResultFound
14
 from sqlalchemy.orm.exc import NoResultFound
15
 from tracim.exceptions import WrongUserPassword, UserNotExist
15
 from tracim.exceptions import WrongUserPassword, UserNotExist
16
 from tracim.exceptions import AuthenticationFailed
16
 from tracim.exceptions import AuthenticationFailed
49
         """
49
         """
50
         Get one user by user id
50
         Get one user by user id
51
         """
51
         """
52
-        return self._base_query().filter(User.user_id == user_id).one()
52
+        try:
53
+            user = self._base_query().filter(User.user_id == user_id).one()
54
+        except NoResultFound:
55
+            raise UserNotExist()
56
+        return user
53
 
57
 
54
     def get_one_by_email(self, email: str) -> User:
58
     def get_one_by_email(self, email: str) -> User:
55
         """
59
         """
57
         :param email: Email of the user
61
         :param email: Email of the user
58
         :return: one user
62
         :return: one user
59
         """
63
         """
60
-        return self._base_query().filter(User.email == email).one()
64
+        try:
65
+            user = self._base_query().filter(User.email == email).one()
66
+        except NoResultFound:
67
+            raise UserNotExist()
68
+        return user
61
 
69
 
62
     # FIXME - G.M - 24-04-2018 - Duplicate method with get_one.
70
     # FIXME - G.M - 24-04-2018 - Duplicate method with get_one.
63
     def get_one_by_id(self, id: int) -> User:
71
     def get_one_by_id(self, id: int) -> User:
98
                 return user
106
                 return user
99
             else:
107
             else:
100
                 raise WrongUserPassword()
108
                 raise WrongUserPassword()
101
-        except (WrongUserPassword, NoResultFound):
109
+        except (WrongUserPassword, NoResultFound, UserNotExist):
102
             raise AuthenticationFailed()
110
             raise AuthenticationFailed()
103
 
111
 
104
     # Actions
112
     # Actions

+ 27 - 6
tracim/lib/core/userworkspace.py Ver arquivo

1
 # -*- coding: utf-8 -*-
1
 # -*- coding: utf-8 -*-
2
 import typing
2
 import typing
3
 
3
 
4
+from tracim import CFG
5
+from tracim.models.context_models import UserRoleWorkspaceInContext
6
+
4
 __author__ = 'damien'
7
 __author__ = 'damien'
5
 
8
 
6
 from sqlalchemy.orm import Session
9
 from sqlalchemy.orm import Session
7
-from tracim.models.auth import User
10
+from tracim.models.auth import User, Group
8
 from tracim.models.data import Workspace
11
 from tracim.models.data import Workspace
9
 from tracim.models.data import UserRoleInWorkspace
12
 from tracim.models.data import UserRoleInWorkspace
10
 from tracim.models.data import RoleType
13
 from tracim.models.data import RoleType
38
         ],
41
         ],
39
     }
42
     }
40
 
43
 
44
+    def get_user_role_workspace_with_context(
45
+            self,
46
+            user_role: UserRoleInWorkspace
47
+    ) -> UserRoleWorkspaceInContext:
48
+        """
49
+        Return WorkspaceInContext object from Workspace
50
+        """
51
+        workspace = UserRoleWorkspaceInContext(
52
+            user_role=user_role,
53
+            dbsession=self._session,
54
+            config=self._config,
55
+        )
56
+        return workspace
57
+
41
     @classmethod
58
     @classmethod
42
     def role_can_read_member_role(cls, reader_role: int, tested_role: int) \
59
     def role_can_read_member_role(cls, reader_role: int, tested_role: int) \
43
             -> bool:
60
             -> bool:
56
 
73
 
57
         return role
74
         return role
58
 
75
 
59
-    def __init__(self, session: Session, current_user: typing.Optional[User]):
76
+    def __init__(self,
77
+                 session: Session,
78
+                 current_user: typing.Optional[User],
79
+                 config: CFG):
60
         self._session = session
80
         self._session = session
61
         self._user = current_user
81
         self._user = current_user
82
+        self._config = config
62
 
83
 
63
     def _get_one_rsc(self, user_id, workspace_id):
84
     def _get_one_rsc(self, user_id, workspace_id):
64
         """
85
         """
99
         return self._session.query(UserRoleInWorkspace)\
120
         return self._session.query(UserRoleInWorkspace)\
100
             .filter(UserRoleInWorkspace.user_id == user_id)
121
             .filter(UserRoleInWorkspace.user_id == user_id)
101
 
122
 
102
-    def get_all_for_user(self, user_id):
103
-        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()
104
 
125
 
105
     def get_all_for_user_order_by_workspace(
126
     def get_all_for_user_order_by_workspace(
106
             self,
127
             self,
109
         return self._get_all_for_user(user_id)\
130
         return self._get_all_for_user(user_id)\
110
             .join(UserRoleInWorkspace.workspace).order_by(Workspace.label).all()
131
             .join(UserRoleInWorkspace.workspace).order_by(Workspace.label).all()
111
 
132
 
112
-    def get_all_for_workspace(self, workspace_id):
133
+    def get_all_for_workspace(self, workspace:Workspace):
113
         return self._session.query(UserRoleInWorkspace)\
134
         return self._session.query(UserRoleInWorkspace)\
114
-            .filter(UserRoleInWorkspace.workspace_id == workspace_id).all()
135
+            .filter(UserRoleInWorkspace.workspace_id == workspace.workspace_id).all()  # nopep8
115
 
136
 
116
     def save(self, role: UserRoleInWorkspace):
137
     def save(self, role: UserRoleInWorkspace):
117
         self._session.flush()
138
         self._session.flush()

+ 20 - 0
tracim/lib/core/workspace.py Ver arquivo

3
 
3
 
4
 from sqlalchemy.orm import Query
4
 from sqlalchemy.orm import Query
5
 from sqlalchemy.orm import Session
5
 from sqlalchemy.orm import Session
6
+
7
+from tracim import CFG
6
 from tracim.lib.utils.translation import fake_translator as _
8
 from tracim.lib.utils.translation import fake_translator as _
7
 
9
 
8
 from tracim.lib.core.userworkspace import RoleApi
10
 from tracim.lib.core.userworkspace import RoleApi
9
 from tracim.models.auth import Group
11
 from tracim.models.auth import Group
10
 from tracim.models.auth import User
12
 from tracim.models.auth import User
13
+from tracim.models.context_models import WorkspaceInContext
11
 from tracim.models.data import UserRoleInWorkspace
14
 from tracim.models.data import UserRoleInWorkspace
12
 from tracim.models.data import Workspace
15
 from tracim.models.data import Workspace
13
 
16
 
20
             self,
23
             self,
21
             session: Session,
24
             session: Session,
22
             current_user: User,
25
             current_user: User,
26
+            config: CFG,
23
             force_role: bool=False
27
             force_role: bool=False
24
     ):
28
     ):
25
         """
29
         """
28
         """
32
         """
29
         self._session = session
33
         self._session = session
30
         self._user = current_user
34
         self._user = current_user
35
+        self._config = config
31
         self._force_role = force_role
36
         self._force_role = force_role
32
 
37
 
33
     def _base_query_without_roles(self):
38
     def _base_query_without_roles(self):
42
             filter(UserRoleInWorkspace.user_id == self._user.user_id).\
47
             filter(UserRoleInWorkspace.user_id == self._user.user_id).\
43
             filter(Workspace.is_deleted == False)
48
             filter(Workspace.is_deleted == False)
44
 
49
 
50
+    def get_workspace_with_context(
51
+            self,
52
+            workspace: Workspace
53
+    ) -> WorkspaceInContext:
54
+        """
55
+        Return WorkspaceInContext object from Workspace
56
+        """
57
+        workspace = WorkspaceInContext(
58
+            workspace=workspace,
59
+            dbsession=self._session,
60
+            config=self._config,
61
+        )
62
+        return workspace
63
+
45
     def create_workspace(
64
     def create_workspace(
46
             self,
65
             self,
47
             label: str='',
66
             label: str='',
62
         role_api = RoleApi(
81
         role_api = RoleApi(
63
             session=self._session,
82
             session=self._session,
64
             current_user=self._user,
83
             current_user=self._user,
84
+            config=self._config
65
         )
85
         )
66
 
86
 
67
         role = role_api.create_one(
87
         role = role_api.create_one(

+ 1 - 0
tracim/lib/mail_notifier/notifier.py Ver arquivo

238
         notifiable_roles = WorkspaceApi(
238
         notifiable_roles = WorkspaceApi(
239
             current_user=user,
239
             current_user=user,
240
             session=self.session,
240
             session=self.session,
241
+            config=self.config
241
         ).get_notifiable_roles(content.workspace)
242
         ).get_notifiable_roles(content.workspace)
242
 
243
 
243
         if len(notifiable_roles) <= 0:
244
         if len(notifiable_roles) <= 0:

+ 2 - 1
tracim/lib/utils/authentification.py Ver arquivo

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

+ 21 - 1
tracim/lib/utils/authorization.py Ver arquivo

44
 # We prefer to use decorators
44
 # We prefer to use decorators
45
 
45
 
46
 
46
 
47
+def require_same_user_or_profile(group):
48
+    """
49
+    Decorator for view to restrict access of tracim request if candidate user
50
+    is distinct from authenticated user and not with high enough profile.
51
+    :param group: value from Group Object
52
+    like Group.TIM_USER or Group.TIM_MANAGER
53
+    :return:
54
+    """
55
+    def decorator(func):
56
+        def wrapper(self, context, request: 'TracimRequest'):
57
+            auth_user = request.current_user
58
+            candidate_user = request.candidate_user
59
+            if auth_user.user_id == candidate_user.user_id or \
60
+                    auth_user.profile.id >= group:
61
+                return func(self, context, request)
62
+            raise InsufficientUserProfile()
63
+        return wrapper
64
+    return decorator
65
+
66
+
47
 def require_profile(group):
67
 def require_profile(group):
48
     """
68
     """
49
     Decorator for view to restrict access of tracim request if profile is
69
     Decorator for view to restrict access of tracim request if profile is
80
             raise InsufficientUserWorkspaceRole()
100
             raise InsufficientUserWorkspaceRole()
81
 
101
 
82
         return wrapper
102
         return wrapper
83
-    return decorator
103
+    return decorator

+ 69 - 8
tracim/lib/utils/request.py Ver arquivo

1
-import typing
1
+# -*- coding: utf-8 -*-
2
+"""
3
+TracimRequest and related functions
4
+"""
2
 from pyramid.request import Request
5
 from pyramid.request import Request
3
 from sqlalchemy.orm.exc import NoResultFound
6
 from sqlalchemy.orm.exc import NoResultFound
4
 
7
 
5
-from tracim.exceptions import NotAuthentificated
8
+from tracim.exceptions import NotAuthentificated, UserNotExist
6
 from tracim.exceptions import WorkspaceNotFound
9
 from tracim.exceptions import WorkspaceNotFound
7
 from tracim.exceptions import ImmutableAttribute
10
 from tracim.exceptions import ImmutableAttribute
8
 from tracim.lib.core.user import UserApi
11
 from tracim.lib.core.user import UserApi
32
             decode_param_names,
35
             decode_param_names,
33
             **kw
36
             **kw
34
         )
37
         )
38
+        # Current workspace, found by request headers or content
35
         self._current_workspace = None  # type: Workspace
39
         self._current_workspace = None  # type: Workspace
40
+        # Authenticated user
36
         self._current_user = None  # type: User
41
         self._current_user = None  # type: User
42
+        # User found from request headers, content, distinct from authenticated
43
+        # user
44
+        self._user_candidate = None  # type: User
37
         # INFO - G.M - 18-05-2018 - Close db at the end of the request
45
         # INFO - G.M - 18-05-2018 - Close db at the end of the request
38
         self.add_finished_callback(self._cleanup)
46
         self.add_finished_callback(self._cleanup)
39
 
47
 
64
 
72
 
65
     @property
73
     @property
66
     def current_user(self) -> User:
74
     def current_user(self) -> User:
75
+        """
76
+        Get user from authentication mecanism.
77
+        """
67
         if self._current_user is None:
78
         if self._current_user is None:
68
-            self.current_user = get_safe_user(self)
79
+            self.current_user = get_auth_safe_user(self)
69
         return self._current_user
80
         return self._current_user
70
 
81
 
71
     @current_user.setter
82
     @current_user.setter
76
             )
87
             )
77
         self._current_user = user
88
         self._current_user = user
78
 
89
 
90
+    # TODO - G.M - 24-05-2018 - Find a better naming for this ?
91
+    @property
92
+    def candidate_user(self) -> User:
93
+        """
94
+        Get user from headers/body request. This user is not
95
+        the one found by authentication mecanism. This user
96
+        can help user to know about who one page is about in
97
+        a similar way as current_workspace.
98
+        """
99
+        if self._user_candidate is None:
100
+            self.candidate_user = get_candidate_user(self)
101
+        return self._user_candidate
102
+
79
     def _cleanup(self, request: 'TracimRequest') -> None:
103
     def _cleanup(self, request: 'TracimRequest') -> None:
80
         """
104
         """
81
         Close dbsession at the end of the request in order to avoid exception
105
         Close dbsession at the end of the request in order to avoid exception
89
         self._current_workspace = None
113
         self._current_workspace = None
90
         self.dbsession.close()
114
         self.dbsession.close()
91
 
115
 
116
+
117
+    @candidate_user.setter
118
+    def candidate_user(self, user: User) -> None:
119
+        if self._user_candidate is not None:
120
+            raise ImmutableAttribute(
121
+                "Can't modify already setted candidate_user"
122
+            )
123
+        self._user_candidate = user
92
 ###
124
 ###
93
 # Utils for TracimRequest
125
 # Utils for TracimRequest
94
 ###
126
 ###
95
 
127
 
96
-def get_safe_user(
128
+
129
+def get_candidate_user(
130
+        request: TracimRequest
131
+) -> User:
132
+    """
133
+    Get candidate user
134
+    :param request: pyramid request
135
+    :return: user found from header/body
136
+    """
137
+    app_config = request.registry.settings['CFG']
138
+    uapi = UserApi(None, session=request.dbsession, config=app_config)
139
+
140
+    try:
141
+        login = None
142
+        if 'user_id' in request.matchdict:
143
+            login = request.matchdict['user_id']
144
+        if not login:
145
+            raise UserNotExist('no user_id found, incorrect request ?')
146
+        user = uapi.get_one(login)
147
+    except NoResultFound:
148
+        raise NotAuthentificated('User not found')
149
+    return user
150
+
151
+
152
+def get_auth_safe_user(
97
         request: TracimRequest,
153
         request: TracimRequest,
98
 ) -> User:
154
 ) -> User:
99
     """
155
     """
126
     """
182
     """
127
     workspace_id = ''
183
     workspace_id = ''
128
     try:
184
     try:
129
-        if 'workspace_id' not in request.json_body:
130
-            raise WorkspaceNotFound('No workspace_id param in json body')
131
-        workspace_id = request.json_body['workspace_id']
132
-        wapi = WorkspaceApi(current_user=user, session=request.dbsession)
185
+        if 'workspace_id' in request.matchdict:
186
+            workspace_id = request.matchdict['workspace_id']
187
+        if not workspace_id:
188
+            raise WorkspaceNotFound('No workspace_id param')
189
+        wapi = WorkspaceApi(
190
+            current_user=user,
191
+            session=request.dbsession,
192
+            config=request.registry.settings['CFG']
193
+        )
133
         workspace = wapi.get_one(workspace_id)
194
         workspace = wapi.get_one(workspace_id)
134
     except JSONDecodeError:
195
     except JSONDecodeError:
135
         raise WorkspaceNotFound('Bad json body')
196
         raise WorkspaceNotFound('Bad json body')

+ 10 - 2
tracim/lib/webdav/dav_provider.py Ver arquivo

72
         if path == root_path:
72
         if path == root_path:
73
             return resources.RootResource(path, environ, user=user, session=session)
73
             return resources.RootResource(path, environ, user=user, session=session)
74
 
74
 
75
-        workspace_api = WorkspaceApi(current_user=user, session=session)
75
+        workspace_api = WorkspaceApi(
76
+            current_user=user,
77
+            session=session,
78
+            config=self.app_config,
79
+        )
76
         workspace = self.get_workspace_from_path(path, workspace_api)
80
         workspace = self.get_workspace_from_path(path, workspace_api)
77
 
81
 
78
         # If the request path is in the form root/name, then we return a WorkspaceResource resource
82
         # If the request path is in the form root/name, then we return a WorkspaceResource resource
194
 
198
 
195
         workspace = self.get_workspace_from_path(
199
         workspace = self.get_workspace_from_path(
196
             path,
200
             path,
197
-            WorkspaceApi(current_user=user, session=session)
201
+            WorkspaceApi(
202
+                current_user=user,
203
+                session=session,
204
+                config=self.app_config,
205
+            )
198
         )
206
         )
199
 
207
 
200
         if parent_path == root_path or workspace is None:
208
         if parent_path == root_path or workspace is None:

+ 3 - 1
tracim/lib/webdav/resources.py Ver arquivo

90
         self.workspace_api = WorkspaceApi(
90
         self.workspace_api = WorkspaceApi(
91
             current_user=self.user,
91
             current_user=self.user,
92
             session=session,
92
             session=session,
93
-            force_role=True
93
+            force_role=True,
94
+            config=self.provider.app_config
94
         )
95
         )
95
 
96
 
96
     def __repr__(self) -> str:
97
     def __repr__(self) -> str:
1254
             workspace_api = WorkspaceApi(
1255
             workspace_api = WorkspaceApi(
1255
                 current_user=self.user,
1256
                 current_user=self.user,
1256
                 session=self.session,
1257
                 session=self.session,
1258
+                config=self.provider.app_config,
1257
                 )
1259
                 )
1258
             content_api = ContentApi(
1260
             content_api = ContentApi(
1259
                 current_user=self.user,
1261
                 current_user=self.user,

+ 87 - 0
tracim/models/applications.py Ver arquivo

1
+# coding=utf-8
2
+import typing
3
+
4
+
5
+class Application(object):
6
+    """
7
+    Application class with data needed for frontend
8
+    """
9
+    def __init__(
10
+            self,
11
+            label: str,
12
+            slug: str,
13
+            icon: str,
14
+            hexcolor: str,
15
+            is_active: bool,
16
+            config: typing.Dict[str, str],
17
+            main_route: str,
18
+    ) -> None:
19
+        self.label = label
20
+        self.slug = slug
21
+        self.icon = icon
22
+        self.hexcolor = hexcolor
23
+        self.is_active = is_active
24
+        self.config = config
25
+        self.main_route = main_route
26
+
27
+
28
+# TODO - G.M - 21-05-2018 Do not rely on hardcoded app list
29
+# default apps
30
+calendar = Application(
31
+    label='Calendar',
32
+    slug='calendar',
33
+    icon='calendar-alt',
34
+    hexcolor='#757575',
35
+    is_active=True,
36
+    config={},
37
+    main_route='/#/workspaces/{workspace_id}/calendar',
38
+)
39
+
40
+thread = Application(
41
+    label='Threads',
42
+    slug='contents/threads',
43
+    icon='comments-o',
44
+    hexcolor='#ad4cf9',
45
+    is_active=True,
46
+    config={},
47
+    main_route='/#/workspaces/{workspace_id}/contents?type=thread',
48
+
49
+)
50
+
51
+file = Application(
52
+    label='Files',
53
+    slug='contents/files',
54
+    icon='paperclip',
55
+    hexcolor='#FF9900',
56
+    is_active=True,
57
+    config={},
58
+    main_route='/#/workspaces/{workspace_id}/contents?type=file',
59
+)
60
+
61
+pagemarkdownplus = Application(
62
+    label='Rich Markdown Files',  # TODO - G.M - 24-05-2018 - Check label
63
+    slug='contents/pagemarkdownplus',
64
+    icon='file-code',
65
+    hexcolor='#f12d2d',
66
+    is_active=True,
67
+    config={},
68
+    main_route='/#/workspaces/{workspace_id}/contents?type=pagemarkdownplus',
69
+)
70
+
71
+pagehtml = Application(
72
+    label='Text Documents',  # TODO - G.M - 24-05-2018 - Check label
73
+    slug='contents/pagehtml',
74
+    icon='file-text-o',
75
+    hexcolor='#3f52e3',
76
+    is_active=True,
77
+    config={},
78
+    main_route='/#/workspaces/{workspace_id}/contents?type=pagehtml',
79
+)
80
+# List of applications
81
+applications = [
82
+    pagehtml,
83
+    pagemarkdownplus,
84
+    file,
85
+    thread,
86
+    calendar,
87
+]

+ 5 - 0
tracim/models/auth.py Ver arquivo

96
              Group.TIM_MANAGER_GROUPNAME,
96
              Group.TIM_MANAGER_GROUPNAME,
97
              Group.TIM_ADMIN_GROUPNAME]
97
              Group.TIM_ADMIN_GROUPNAME]
98
 
98
 
99
+    _IDS = [Group.TIM_NOBODY,
100
+            Group.TIM_USER,
101
+            Group.TIM_MANAGER,
102
+            Group.TIM_ADMIN]
103
+
99
     # TODO - G.M - 18-04-2018 [Cleanup] Drop this
104
     # TODO - G.M - 18-04-2018 [Cleanup] Drop this
100
     # _LABEL = [l_('Nobody'),
105
     # _LABEL = [l_('Nobody'),
101
     #           l_('Users'),
106
     #           l_('Users'),

+ 137 - 0
tracim/models/context_models.py Ver arquivo

2
 import typing
2
 import typing
3
 from datetime import datetime
3
 from datetime import datetime
4
 
4
 
5
+from slugify import slugify
5
 from sqlalchemy.orm import Session
6
 from sqlalchemy.orm import Session
6
 from tracim import CFG
7
 from tracim import CFG
7
 from tracim.models import User
8
 from tracim.models import User
8
 from tracim.models.auth import Profile
9
 from tracim.models.auth import Profile
10
+from tracim.models.data import Workspace, UserRoleInWorkspace
11
+from tracim.models.workspace_menu_entries import default_workspace_menu_entry, \
12
+    WorkspaceMenuEntry
9
 
13
 
10
 
14
 
11
 class LoginCredentials(object):
15
 class LoginCredentials(object):
74
     def avatar_url(self) -> typing.Optional[str]:
78
     def avatar_url(self) -> typing.Optional[str]:
75
         # TODO - G-M - 20-04-2018 - [Avatar] Add user avatar feature
79
         # TODO - G-M - 20-04-2018 - [Avatar] Add user avatar feature
76
         return None
80
         return None
81
+
82
+
83
+class WorkspaceInContext(object):
84
+    """
85
+    Interface to get Workspace data and Workspace data related to context.
86
+    """
87
+
88
+    def __init__(self, workspace: Workspace, dbsession: Session, config: CFG):
89
+        self.workspace = workspace
90
+        self.dbsession = dbsession
91
+        self.config = config
92
+
93
+    @property
94
+    def workspace_id(self) -> int:
95
+        """
96
+        numeric id of the workspace.
97
+        """
98
+        return self.workspace.workspace_id
99
+
100
+    @property
101
+    def id(self) -> int:
102
+        """
103
+        alias of workspace_id
104
+        """
105
+        return self.workspace_id
106
+
107
+    @property
108
+    def label(self) -> str:
109
+        """
110
+        get workspace label
111
+        """
112
+        return self.workspace.label
113
+
114
+    @property
115
+    def description(self) -> str:
116
+        """
117
+        get workspace description
118
+        """
119
+        return self.workspace.description
120
+
121
+    @property
122
+    def slug(self) -> str:
123
+        """
124
+        get workspace slug
125
+        """
126
+        return slugify(self.workspace.label)
127
+
128
+    @property
129
+    def sidebar_entries(self) -> typing.List[WorkspaceMenuEntry]:
130
+        """
131
+        get sidebar entries, those depends on activated apps.
132
+        """
133
+        # TODO - G.M - 22-05-2018 - Rework on this in
134
+        # order to not use hardcoded list
135
+        # list should be able to change (depending on activated/disabled
136
+        # apps)
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 role_id(self) -> int:
175
+        """
176
+        role as int id, each value refer to a different role.
177
+        """
178
+        return self.user_role.role
179
+
180
+    @property
181
+    def role_slug(self) -> str:
182
+        """
183
+        simple name of the role of the user.
184
+        can be anything from UserRoleInWorkspace SLUG, like
185
+        'not_applicable', 'reader',
186
+        'contributor', 'content_manager', 'workspace_manager'
187
+        :return: user workspace role as slug.
188
+        """
189
+        return UserRoleInWorkspace.SLUG[self.user_role.role]
190
+
191
+    @property
192
+    def user(self) -> UserInContext:
193
+        """
194
+        User who has this role, with context data
195
+        :return: UserInContext object
196
+        """
197
+        return UserInContext(
198
+            self.user_role.user,
199
+            self.dbsession,
200
+            self.config
201
+        )
202
+
203
+    @property
204
+    def workspace(self) -> WorkspaceInContext:
205
+        """
206
+        Workspace related to this role, with his context data
207
+        :return: WorkspaceInContext object
208
+        """
209
+        return WorkspaceInContext(
210
+            self.user_role.workspace,
211
+            self.dbsession,
212
+            self.config
213
+        )

+ 23 - 1
tracim/models/data.py Ver arquivo

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
+
135
+    SLUG = dict()
136
+    SLUG[NOT_APPLICABLE] = 'not_applicable'
137
+    SLUG[READER] = 'reader'
138
+    SLUG[CONTRIBUTOR] = 'contributor'
139
+    SLUG[CONTENT_MANAGER] = 'content_manager'
140
+    SLUG[WORKSPACE_MANAGER] = 'workspace_manager'
141
+
134
     LABEL = dict()
142
     LABEL = dict()
135
     LABEL[0] = l_('N/A')
143
     LABEL[0] = l_('N/A')
136
     LABEL[1] = l_('Reader')
144
     LABEL[1] = l_('Reader')
166
         return UserRoleInWorkspace.LABEL[self.role]
174
         return UserRoleInWorkspace.LABEL[self.role]
167
 
175
 
168
     @classmethod
176
     @classmethod
169
-    def get_all_role_values(self):
177
+    def get_all_role_values(cls) -> typing.List[int]:
178
+        """
179
+        Return all valid role value
180
+        """
170
         return [
181
         return [
171
             UserRoleInWorkspace.READER,
182
             UserRoleInWorkspace.READER,
172
             UserRoleInWorkspace.CONTRIBUTOR,
183
             UserRoleInWorkspace.CONTRIBUTOR,
174
             UserRoleInWorkspace.WORKSPACE_MANAGER
185
             UserRoleInWorkspace.WORKSPACE_MANAGER
175
         ]
186
         ]
176
 
187
 
188
+    @classmethod
189
+    def get_all_role_slug(cls) -> typing.List[str]:
190
+        """
191
+        Return all valid role slug
192
+        """
193
+        # INFO - G.M - 25-05-2018 - Be carefull, as long as this method
194
+        # and get_all_role_values are both used for API, this method should
195
+        # return item in the same order as get_all_role_values
196
+        return [cls.SLUG[value] for value in cls.get_all_role_values()]
197
+
198
+
177
 class RoleType(object):
199
 class RoleType(object):
178
     def __init__(self, role_id):
200
     def __init__(self, role_id):
179
         self.role_type_id = role_id
201
         self.role_type_id = role_id

+ 71 - 0
tracim/models/workspace_menu_entries.py Ver arquivo

1
+# coding=utf-8
2
+import typing
3
+from copy import copy
4
+
5
+from tracim.models.applications import applications
6
+from tracim.models.data import Workspace
7
+
8
+
9
+class WorkspaceMenuEntry(object):
10
+    """
11
+    Application class with data needed for frontend
12
+    """
13
+    def __init__(
14
+            self,
15
+            label: str,
16
+            slug: str,
17
+            icon: str,
18
+            hexcolor: str,
19
+            route: str,
20
+    ) -> None:
21
+        self.slug = slug
22
+        self.label = label
23
+        self.route = route
24
+        self.hexcolor = hexcolor
25
+        self.icon = icon
26
+
27
+
28
+dashboard_menu_entry = WorkspaceMenuEntry(
29
+  slug='dashboard',
30
+  label='Dashboard',
31
+  route='/#/workspaces/{workspace_id}/dashboard',
32
+  hexcolor='#252525',
33
+  icon="",
34
+)
35
+all_content_menu_entry = WorkspaceMenuEntry(
36
+  slug="contents/all",
37
+  label="All Contents",
38
+  route="/#/workspaces/{workspace_id}/contents",
39
+  hexcolor="#fdfdfd",
40
+  icon="",
41
+)
42
+
43
+
44
+def default_workspace_menu_entry(
45
+    workspace: Workspace,
46
+)-> typing.List[WorkspaceMenuEntry]:
47
+    """
48
+    Get default menu entry for a workspace
49
+    """
50
+    menu_entries = [
51
+        copy(dashboard_menu_entry),
52
+        copy(all_content_menu_entry),
53
+    ]
54
+    for app in applications:
55
+        if app.main_route:
56
+            new_entry = WorkspaceMenuEntry(
57
+                slug=app.slug,
58
+                label=app.label,
59
+                hexcolor=app.hexcolor,
60
+                icon=app.icon,
61
+                route=app.main_route
62
+            )
63
+            menu_entries.append(new_entry)
64
+
65
+    for entry in menu_entries:
66
+        entry.route = entry.route.replace(
67
+            '{workspace_id}',
68
+            str(workspace.workspace_id)
69
+        )
70
+
71
+    return menu_entries

+ 7 - 5
tracim/tests/__init__.py Ver arquivo

45
 
45
 
46
         }
46
         }
47
         hapic.reset_context()
47
         hapic.reset_context()
48
+        self.engine = get_engine(self.settings)
49
+        DeclarativeBase.metadata.create_all(self.engine)
50
+        self.session_factory = get_session_factory(self.engine)
51
+        self.app_config = CFG(self.settings)
52
+        self.app_config.configure_filedepot()
48
         self.init_database(self.settings)
53
         self.init_database(self.settings)
54
+        DepotManager._clear()
49
         self.run_app()
55
         self.run_app()
50
 
56
 
51
     def run_app(self):
57
     def run_app(self):
52
         app = web({}, **self.settings)
58
         app = web({}, **self.settings)
53
-        self.init_database(self.settings)
54
         self.testapp = TestApp(app)
59
         self.testapp = TestApp(app)
55
 
60
 
56
     def init_database(self, settings):
61
     def init_database(self, settings):
57
-        self.engine = get_engine(settings)
58
-        DeclarativeBase.metadata.create_all(self.engine)
59
-        self.session_factory = get_session_factory(self.engine)
60
-        self.app_config = CFG(settings)
61
         with transaction.manager:
62
         with transaction.manager:
62
             dbsession = get_tm_session(self.session_factory, transaction.manager)
63
             dbsession = get_tm_session(self.session_factory, transaction.manager)
63
             try:
64
             try:
171
         WorkspaceApi(
172
         WorkspaceApi(
172
             current_user=user,
173
             current_user=user,
173
             session=self.session,
174
             session=self.session,
175
+            config=self.app_config,
174
         ).create_workspace(name, save_now=True)
176
         ).create_workspace(name, save_now=True)
175
 
177
 
176
         eq_(
178
         eq_(

+ 3 - 3
tracim/tests/commands/test_commands.py Ver arquivo

11
 from tracim.command import TracimCLI
11
 from tracim.command import TracimCLI
12
 from tracim.command.user import UserCommand
12
 from tracim.command.user import UserCommand
13
 from tracim.exceptions import UserAlreadyExistError, BadCommandError, \
13
 from tracim.exceptions import UserAlreadyExistError, BadCommandError, \
14
-    GroupNotExist
14
+    GroupNotExist, UserNotExist
15
 from tracim.lib.core.user import UserApi
15
 from tracim.lib.core.user import UserApi
16
 from tracim.tests import CommandFunctionalTest
16
 from tracim.tests import CommandFunctionalTest
17
 
17
 
48
             session=self.session,
48
             session=self.session,
49
             config=self.app_config,
49
             config=self.app_config,
50
         )
50
         )
51
-        with pytest.raises(NoResultFound):
51
+        with pytest.raises(UserNotExist):
52
             api.get_one_by_email('command_test@user')
52
             api.get_one_by_email('command_test@user')
53
         app = TracimCLI()
53
         app = TracimCLI()
54
         result = app.run([
54
         result = app.run([
72
             session=self.session,
72
             session=self.session,
73
             config=self.app_config,
73
             config=self.app_config,
74
         )
74
         )
75
-        with pytest.raises(NoResultFound):
75
+        with pytest.raises(UserNotExist):
76
             api.get_one_by_email('command_test@user')
76
             api.get_one_by_email('command_test@user')
77
         app = TracimCLI()
77
         app = TracimCLI()
78
         result = app.run([
78
         result = app.run([

+ 2 - 0
tracim/tests/functional/test_mail_notification.py Ver arquivo

127
         wapi = WorkspaceApi(
127
         wapi = WorkspaceApi(
128
             current_user=current_user,
128
             current_user=current_user,
129
             session=self.session,
129
             session=self.session,
130
+            config=self.app_config,
130
         )
131
         )
131
         workspace = wapi.get_one_by_label('w1')
132
         workspace = wapi.get_one_by_label('w1')
132
         user = uapi.get_one_by_email('bob@fsf.local')
133
         user = uapi.get_one_by_email('bob@fsf.local')
218
         wapi = WorkspaceApi(
219
         wapi = WorkspaceApi(
219
             current_user=current_user,
220
             current_user=current_user,
220
             session=self.session,
221
             session=self.session,
222
+            config=self.app_config,
221
         )
223
         )
222
         workspace = wapi.get_one_by_label('w1')
224
         workspace = wapi.get_one_by_label('w1')
223
         user = uapi.get_one_by_email('bob@fsf.local')
225
         user = uapi.get_one_by_email('bob@fsf.local')

+ 77 - 0
tracim/tests/functional/test_system.py Ver arquivo

1
+# coding=utf-8
2
+"""
3
+Tests for /api/v2/system subpath endpoints.
4
+"""
5
+from tracim.tests import FunctionalTest
6
+
7
+
8
+class TestApplicationsEndpoint(FunctionalTest):
9
+    """
10
+    Tests for /api/v2/system/applications
11
+    """
12
+
13
+    def test_api__get_applications__ok_200__nominal_case(self):
14
+        """
15
+        Get applications list with a registered user.
16
+        """
17
+        self.testapp.authorization = (
18
+            'Basic',
19
+            (
20
+                'admin@admin.admin',
21
+                'admin@admin.admin'
22
+            )
23
+        )
24
+        res = self.testapp.get('/api/v2/system/applications', status=200)
25
+        res = res.json_body
26
+        application = res[0]
27
+        assert application['label'] == "Text Documents"
28
+        assert application['slug'] == 'contents/pagehtml'
29
+        assert application['icon'] == 'file-text-o'
30
+        assert application['hexcolor'] == '#3f52e3'
31
+        assert application['is_active'] is True
32
+        assert 'config' in application
33
+        application = res[1]
34
+        assert application['label'] == "Rich Markdown Files"
35
+        assert application['slug'] == 'contents/pagemarkdownplus'
36
+        assert application['icon'] == 'file-code'
37
+        assert application['hexcolor'] == '#f12d2d'
38
+        assert application['is_active'] is True
39
+        assert 'config' in application
40
+        application = res[2]
41
+        assert application['label'] == "Files"
42
+        assert application['slug'] == 'contents/files'
43
+        assert application['icon'] == 'paperclip'
44
+        assert application['hexcolor'] == '#FF9900'
45
+        assert application['is_active'] is True
46
+        assert 'config' in application
47
+        application = res[3]
48
+        assert application['label'] == "Threads"
49
+        assert application['slug'] == 'contents/threads'
50
+        assert application['icon'] == 'comments-o'
51
+        assert application['hexcolor'] == '#ad4cf9'
52
+        assert application['is_active'] is True
53
+        assert 'config' in application
54
+        application = res[4]
55
+        assert application['label'] == "Calendar"
56
+        assert application['slug'] == 'calendar'
57
+        assert application['icon'] == 'calendar-alt'
58
+        assert application['hexcolor'] == '#757575'
59
+        assert application['is_active'] is True
60
+        assert 'config' in application
61
+
62
+    def test_api__get_workspace__err_401__unregistered_user(self):
63
+        """
64
+        Get applications list with an unregistered user (bad auth)
65
+        """
66
+        self.testapp.authorization = (
67
+            'Basic',
68
+            (
69
+                'john@doe.doe',
70
+                'lapin'
71
+            )
72
+        )
73
+        res = self.testapp.get('/api/v2/system/applications', status=401)
74
+        assert isinstance(res.json, dict)
75
+        assert 'code' in res.json.keys()
76
+        assert 'message' in res.json.keys()
77
+        assert 'details' in res.json.keys()

+ 137 - 0
tracim/tests/functional/test_user.py Ver arquivo

1
+# -*- coding: utf-8 -*-
2
+"""
3
+Tests for /api/v2/users subpath endpoints.
4
+"""
5
+from tracim.tests import FunctionalTest
6
+from tracim.fixtures.content import Content as ContentFixtures
7
+from tracim.fixtures.users_and_groups import Base as BaseFixture
8
+
9
+
10
+class TestUserWorkspaceEndpoint(FunctionalTest):
11
+    # -*- coding: utf-8 -*-
12
+    """
13
+    Tests for /api/v2/users/{user_id}/workspaces
14
+    """
15
+    fixtures = [BaseFixture, ContentFixtures]
16
+
17
+    def test_api__get_user_workspaces__ok_200__nominal_case(self):
18
+        """
19
+        Check obtain all workspaces reachables for user with user auth.
20
+        """
21
+        self.testapp.authorization = (
22
+            'Basic',
23
+            (
24
+                'admin@admin.admin',
25
+                'admin@admin.admin'
26
+            )
27
+        )
28
+        res = self.testapp.get('/api/v2/users/1/workspaces', status=200)
29
+        res = res.json_body
30
+        workspace = res[0]
31
+        assert workspace['id'] == 1
32
+        assert workspace['label'] == 'w1'
33
+        assert len(workspace['sidebar_entries']) == 7
34
+
35
+        sidebar_entry = workspace['sidebar_entries'][0]
36
+        assert sidebar_entry['slug'] == 'dashboard'
37
+        assert sidebar_entry['label'] == 'Dashboard'
38
+        assert sidebar_entry['route'] == '/#/workspaces/1/dashboard'  # nopep8
39
+        assert sidebar_entry['hexcolor'] == "#252525"
40
+        assert sidebar_entry['icon'] == ""
41
+
42
+        sidebar_entry = workspace['sidebar_entries'][1]
43
+        assert sidebar_entry['slug'] == 'contents/all'
44
+        assert sidebar_entry['label'] == 'All Contents'
45
+        assert sidebar_entry['route'] == "/#/workspaces/1/contents"  # nopep8
46
+        assert sidebar_entry['hexcolor'] == "#fdfdfd"
47
+        assert sidebar_entry['icon'] == ""
48
+
49
+        sidebar_entry = workspace['sidebar_entries'][2]
50
+        assert sidebar_entry['slug'] == 'contents/pagehtml'
51
+        assert sidebar_entry['label'] == 'Text Documents'
52
+        assert sidebar_entry['route'] == '/#/workspaces/1/contents?type=pagehtml'  # nopep8
53
+        assert sidebar_entry['hexcolor'] == "#3f52e3"
54
+        assert sidebar_entry['icon'] == "file-text-o"
55
+
56
+        sidebar_entry = workspace['sidebar_entries'][3]
57
+        assert sidebar_entry['slug'] == 'contents/pagemarkdownplus'
58
+        assert sidebar_entry['label'] == 'Rich Markdown Files'
59
+        assert sidebar_entry['route'] == "/#/workspaces/1/contents?type=pagemarkdownplus"    # nopep8
60
+        assert sidebar_entry['hexcolor'] == "#f12d2d"
61
+        assert sidebar_entry['icon'] == "file-code"
62
+
63
+        sidebar_entry = workspace['sidebar_entries'][4]
64
+        assert sidebar_entry['slug'] == 'contents/files'
65
+        assert sidebar_entry['label'] == 'Files'
66
+        assert sidebar_entry['route'] == "/#/workspaces/1/contents?type=file"  # nopep8
67
+        assert sidebar_entry['hexcolor'] == "#FF9900"
68
+        assert sidebar_entry['icon'] == "paperclip"
69
+
70
+        sidebar_entry = workspace['sidebar_entries'][5]
71
+        assert sidebar_entry['slug'] == 'contents/threads'
72
+        assert sidebar_entry['label'] == 'Threads'
73
+        assert sidebar_entry['route'] == "/#/workspaces/1/contents?type=thread"  # nopep8
74
+        assert sidebar_entry['hexcolor'] == "#ad4cf9"
75
+        assert sidebar_entry['icon'] == "comments-o"
76
+
77
+        sidebar_entry = workspace['sidebar_entries'][6]
78
+        assert sidebar_entry['slug'] == 'calendar'
79
+        assert sidebar_entry['label'] == 'Calendar'
80
+        assert sidebar_entry['route'] == "/#/workspaces/1/calendar"  # nopep8
81
+        assert sidebar_entry['hexcolor'] == "#757575"
82
+        assert sidebar_entry['icon'] == "calendar-alt"
83
+
84
+    def test_api__get_user_workspaces__err_403__unallowed_user(self):
85
+        """
86
+        Check obtain all workspaces reachables for one user
87
+        with another non-admin user auth.
88
+        """
89
+        self.testapp.authorization = (
90
+            'Basic',
91
+            (
92
+                'lawrence-not-real-email@fsf.local',
93
+                'foobarbaz'
94
+            )
95
+        )
96
+        res = self.testapp.get('/api/v2/users/1/workspaces', status=403)
97
+        assert isinstance(res.json, dict)
98
+        assert 'code' in res.json.keys()
99
+        assert 'message' in res.json.keys()
100
+        assert 'details' in res.json.keys()
101
+
102
+    def test_api__get_user_workspaces__err_401__unregistered_user(self):
103
+        """
104
+        Check obtain all workspaces reachables for one user
105
+        without correct user auth (user unregistered).
106
+        """
107
+        self.testapp.authorization = (
108
+            'Basic',
109
+            (
110
+                'john@doe.doe',
111
+                'lapin'
112
+            )
113
+        )
114
+        res = self.testapp.get('/api/v2/users/1/workspaces', status=401)
115
+        assert isinstance(res.json, dict)
116
+        assert 'code' in res.json.keys()
117
+        assert 'message' in res.json.keys()
118
+        assert 'details' in res.json.keys()
119
+
120
+    def test_api__get_user_workspaces__err_404__user_does_not_exist(self):
121
+        """
122
+        Check obtain all workspaces reachables for one user who does
123
+        not exist
124
+        with a correct user auth.
125
+        """
126
+        self.testapp.authorization = (
127
+            'Basic',
128
+            (
129
+                'admin@admin.admin',
130
+                'admin@admin.admin'
131
+            )
132
+        )
133
+        res = self.testapp.get('/api/v2/users/5/workspaces', status=404)
134
+        assert isinstance(res.json, dict)
135
+        assert 'code' in res.json.keys()
136
+        assert 'message' in res.json.keys()
137
+        assert 'details' in res.json.keys()

+ 218 - 0
tracim/tests/functional/test_workspaces.py Ver arquivo

1
+# -*- coding: utf-8 -*-
2
+"""
3
+Tests for /api/v2/workspaces subpath endpoints.
4
+"""
5
+from tracim.tests import FunctionalTest
6
+from tracim.fixtures.content import Content as ContentFixtures
7
+from tracim.fixtures.users_and_groups import Base as BaseFixture
8
+
9
+
10
+class TestWorkspaceEndpoint(FunctionalTest):
11
+    """
12
+    Tests for /api/v2/workspaces/{workspace_id} endpoint
13
+    """
14
+
15
+    fixtures = [BaseFixture, ContentFixtures]
16
+
17
+    def test_api__get_workspace__ok_200__nominal_case(self) -> None:
18
+        """
19
+        Check obtain workspace reachable for user.
20
+        """
21
+        self.testapp.authorization = (
22
+            'Basic',
23
+            (
24
+                'admin@admin.admin',
25
+                'admin@admin.admin'
26
+            )
27
+        )
28
+        res = self.testapp.get('/api/v2/workspaces/1', status=200)
29
+        workspace = res.json_body
30
+        assert workspace['id'] == 1
31
+        assert workspace['slug'] == 'w1'
32
+        assert workspace['label'] == 'w1'
33
+        assert workspace['description'] == 'This is a workspace'
34
+        assert len(workspace['sidebar_entries']) == 7
35
+
36
+        sidebar_entry = workspace['sidebar_entries'][0]
37
+        assert sidebar_entry['slug'] == 'dashboard'
38
+        assert sidebar_entry['label'] == 'Dashboard'
39
+        assert sidebar_entry['route'] == '/#/workspaces/1/dashboard'  # nopep8
40
+        assert sidebar_entry['hexcolor'] == "#252525"
41
+        assert sidebar_entry['icon'] == ""
42
+
43
+        sidebar_entry = workspace['sidebar_entries'][1]
44
+        assert sidebar_entry['slug'] == 'contents/all'
45
+        assert sidebar_entry['label'] == 'All Contents'
46
+        assert sidebar_entry['route'] == "/#/workspaces/1/contents"  # nopep8
47
+        assert sidebar_entry['hexcolor'] == "#fdfdfd"
48
+        assert sidebar_entry['icon'] == ""
49
+
50
+        sidebar_entry = workspace['sidebar_entries'][2]
51
+        assert sidebar_entry['slug'] == 'contents/pagehtml'
52
+        assert sidebar_entry['label'] == 'Text Documents'
53
+        assert sidebar_entry['route'] == '/#/workspaces/1/contents?type=pagehtml'  # nopep8
54
+        assert sidebar_entry['hexcolor'] == "#3f52e3"
55
+        assert sidebar_entry['icon'] == "file-text-o"
56
+
57
+        sidebar_entry = workspace['sidebar_entries'][3]
58
+        assert sidebar_entry['slug'] == 'contents/pagemarkdownplus'
59
+        assert sidebar_entry['label'] == 'Rich Markdown Files'
60
+        assert sidebar_entry['route'] == "/#/workspaces/1/contents?type=pagemarkdownplus"    # nopep8
61
+        assert sidebar_entry['hexcolor'] == "#f12d2d"
62
+        assert sidebar_entry['icon'] == "file-code"
63
+
64
+        sidebar_entry = workspace['sidebar_entries'][4]
65
+        assert sidebar_entry['slug'] == 'contents/files'
66
+        assert sidebar_entry['label'] == 'Files'
67
+        assert sidebar_entry['route'] == "/#/workspaces/1/contents?type=file"  # nopep8
68
+        assert sidebar_entry['hexcolor'] == "#FF9900"
69
+        assert sidebar_entry['icon'] == "paperclip"
70
+
71
+        sidebar_entry = workspace['sidebar_entries'][5]
72
+        assert sidebar_entry['slug'] == 'contents/threads'
73
+        assert sidebar_entry['label'] == 'Threads'
74
+        assert sidebar_entry['route'] == "/#/workspaces/1/contents?type=thread"  # nopep8
75
+        assert sidebar_entry['hexcolor'] == "#ad4cf9"
76
+        assert sidebar_entry['icon'] == "comments-o"
77
+
78
+        sidebar_entry = workspace['sidebar_entries'][6]
79
+        assert sidebar_entry['slug'] == 'calendar'
80
+        assert sidebar_entry['label'] == 'Calendar'
81
+        assert sidebar_entry['route'] == "/#/workspaces/1/calendar"  # nopep8
82
+        assert sidebar_entry['hexcolor'] == "#757575"
83
+        assert sidebar_entry['icon'] == "calendar-alt"
84
+
85
+    def test_api__get_workspace__err_403__unallowed_user(self) -> None:
86
+        """
87
+        Check obtain workspace unreachable for user
88
+        """
89
+        self.testapp.authorization = (
90
+            'Basic',
91
+            (
92
+                'lawrence-not-real-email@fsf.local',
93
+                'foobarbaz'
94
+            )
95
+        )
96
+        res = self.testapp.get('/api/v2/workspaces/1', status=403)
97
+        assert isinstance(res.json, dict)
98
+        assert 'code' in res.json.keys()
99
+        assert 'message' in res.json.keys()
100
+        assert 'details' in res.json.keys()
101
+
102
+    def test_api__get_workspace__err_401__unregistered_user(self) -> None:
103
+        """
104
+        Check obtain workspace without registered user.
105
+        """
106
+        self.testapp.authorization = (
107
+            'Basic',
108
+            (
109
+                'john@doe.doe',
110
+                'lapin'
111
+            )
112
+        )
113
+        res = self.testapp.get('/api/v2/workspaces/1', status=401)
114
+        assert isinstance(res.json, dict)
115
+        assert 'code' in res.json.keys()
116
+        assert 'message' in res.json.keys()
117
+        assert 'details' in res.json.keys()
118
+
119
+    def test_api__get_workspace__err_403__workspace_does_not_exist(self) -> None:  # nopep8
120
+        """
121
+        Check obtain workspace who does not exist with an existing user.
122
+        """
123
+        self.testapp.authorization = (
124
+            'Basic',
125
+            (
126
+                'admin@admin.admin',
127
+                'admin@admin.admin'
128
+            )
129
+        )
130
+        res = self.testapp.get('/api/v2/workspaces/5', status=403)
131
+        assert isinstance(res.json, dict)
132
+        assert 'code' in res.json.keys()
133
+        assert 'message' in res.json.keys()
134
+        assert 'details' in res.json.keys()
135
+
136
+
137
+class TestWorkspaceMembersEndpoint(FunctionalTest):
138
+    """
139
+    Tests for /api/v2/workspaces/{workspace_id}/members endpoint
140
+    """
141
+
142
+    fixtures = [BaseFixture, ContentFixtures]
143
+
144
+    def test_api__get_workspace_members__ok_200__nominal_case(self):
145
+        """
146
+        Check obtain workspace members list with a reachable workspace for user
147
+        """
148
+        self.testapp.authorization = (
149
+            'Basic',
150
+            (
151
+                'admin@admin.admin',
152
+                'admin@admin.admin'
153
+            )
154
+        )
155
+        res = self.testapp.get('/api/v2/workspaces/1/members', status=200).json_body   # nopep8
156
+        assert len(res) == 2
157
+        user_role = res[0]
158
+        assert user_role['role_slug'] == 'workspace_manager'
159
+        assert user_role['role_id'] == 8
160
+        assert user_role['user_id'] == 1
161
+        assert user_role['workspace_id'] == 1
162
+        assert user_role['user']['display_name'] == 'Global manager'
163
+        # TODO - G.M - 24-05-2018 - [Avatar] Replace
164
+        # by correct value when avatar feature will be enabled
165
+        assert user_role['user']['avatar_url'] is None
166
+
167
+    def test_api__get_workspace_members__err_403__unallowed_user(self):
168
+        """
169
+        Check obtain workspace members list with an unreachable workspace for
170
+        user
171
+        """
172
+        self.testapp.authorization = (
173
+            'Basic',
174
+            (
175
+                'lawrence-not-real-email@fsf.local',
176
+                'foobarbaz'
177
+            )
178
+        )
179
+        res = self.testapp.get('/api/v2/workspaces/3/members', status=403)
180
+        assert isinstance(res.json, dict)
181
+        assert 'code' in res.json.keys()
182
+        assert 'message' in res.json.keys()
183
+        assert 'details' in res.json.keys()
184
+
185
+    def test_api__get_workspace_members__err_401__unregistered_user(self):
186
+        """
187
+        Check obtain workspace members list with an unregistered user
188
+        """
189
+        self.testapp.authorization = (
190
+            'Basic',
191
+            (
192
+                'john@doe.doe',
193
+                'lapin'
194
+            )
195
+        )
196
+        res = self.testapp.get('/api/v2/workspaces/1/members', status=401)
197
+        assert isinstance(res.json, dict)
198
+        assert 'code' in res.json.keys()
199
+        assert 'message' in res.json.keys()
200
+        assert 'details' in res.json.keys()
201
+
202
+    def test_api__get_workspace_members__err_403__workspace_does_not_exist(self):  # nopep8
203
+        """
204
+        Check obtain workspace members list with an existing user but
205
+        an unexisting workspace
206
+        """
207
+        self.testapp.authorization = (
208
+            'Basic',
209
+            (
210
+                'admin@admin.admin',
211
+                'admin@admin.admin'
212
+            )
213
+        )
214
+        res = self.testapp.get('/api/v2/workspaces/5/members', status=403)
215
+        assert isinstance(res.json, dict)
216
+        assert 'code' in res.json.keys()
217
+        assert 'message' in res.json.keys()
218
+        assert 'details' in res.json.keys()

+ 222 - 61
tracim/tests/library/test_content_api.py Ver arquivo

107
             config=self.app_config,
107
             config=self.app_config,
108
             current_user=None,
108
             current_user=None,
109
         )
109
         )
110
-        group_api = GroupApi(current_user=None,session=self.session)
110
+        group_api = GroupApi(
111
+            current_user=None,
112
+            session=self.session,
113
+            config=self.app_config,
114
+        )
111
         groups = [group_api.get_one(Group.TIM_USER),
115
         groups = [group_api.get_one(Group.TIM_USER),
112
                   group_api.get_one(Group.TIM_MANAGER),
116
                   group_api.get_one(Group.TIM_MANAGER),
113
                   group_api.get_one(Group.TIM_ADMIN)]
117
                   group_api.get_one(Group.TIM_ADMIN)]
116
                                         groups=groups, save_now=True)
120
                                         groups=groups, save_now=True)
117
         workspace = WorkspaceApi(
121
         workspace = WorkspaceApi(
118
             current_user=user,
122
             current_user=user,
119
-            session=self.session
123
+            session=self.session,
124
+            config=self.app_config,
120
         ).create_workspace('test workspace', save_now=True)
125
         ).create_workspace('test workspace', save_now=True)
121
         api = ContentApi(
126
         api = ContentApi(
122
             current_user=user,
127
             current_user=user,
133
 
138
 
134
         # Refresh instances after commit
139
         # Refresh instances after commit
135
         user = uapi.get_one(uid)
140
         user = uapi.get_one(uid)
136
-        workspace_api = WorkspaceApi(current_user=user, session=self.session)
141
+        workspace_api = WorkspaceApi(
142
+            current_user=user,
143
+            session=self.session,
144
+            config=self.app_config
145
+        )
137
         workspace = workspace_api.get_one(wid)
146
         workspace = workspace_api.get_one(wid)
138
         api = ContentApi(
147
         api = ContentApi(
139
             current_user=user,
148
             current_user=user,
154
 
163
 
155
         # Refresh instances after commit
164
         # Refresh instances after commit
156
         user = uapi.get_one(uid)
165
         user = uapi.get_one(uid)
157
-        workspace_api = WorkspaceApi(current_user=user, session=self.session)
166
+        workspace_api = WorkspaceApi(
167
+            current_user=user,
168
+            session=self.session,
169
+            config=self.app_config
170
+        )
158
         workspace = workspace_api.get_one(wid)
171
         workspace = workspace_api.get_one(wid)
159
         api = ContentApi(
172
         api = ContentApi(
160
             current_user=user, 
173
             current_user=user, 
168
         # Test that the item is still available if "show deleted" is activated
181
         # Test that the item is still available if "show deleted" is activated
169
         # Refresh instances after commit
182
         # Refresh instances after commit
170
         user = uapi.get_one(uid)
183
         user = uapi.get_one(uid)
171
-        workspace_api = WorkspaceApi(current_user=user, session=self.session)
184
+        workspace_api = WorkspaceApi(
185
+            current_user=user,
186
+            session=self.session,
187
+            config=self.app_config,
188
+        )
172
         api = ContentApi(
189
         api = ContentApi(
173
             current_user=user,
190
             current_user=user,
174
             session=self.session,
191
             session=self.session,
184
             config=self.app_config,
201
             config=self.app_config,
185
             current_user=None,
202
             current_user=None,
186
         )
203
         )
187
-        group_api = GroupApi(current_user=None, session=self.session)
204
+        group_api = GroupApi(
205
+            current_user=None,
206
+            session=self.session,
207
+            config=self.app_config,
208
+        )
188
         groups = [group_api.get_one(Group.TIM_USER),
209
         groups = [group_api.get_one(Group.TIM_USER),
189
                   group_api.get_one(Group.TIM_MANAGER),
210
                   group_api.get_one(Group.TIM_MANAGER),
190
                   group_api.get_one(Group.TIM_ADMIN)]
211
                   group_api.get_one(Group.TIM_ADMIN)]
191
 
212
 
192
-        user = uapi.create_minimal_user(email='this.is@user',
193
-                                        groups=groups, save_now=True)
194
-        workspace_api = WorkspaceApi(current_user=user, session=self.session)
213
+        user = uapi.create_minimal_user(
214
+            email='this.is@user',
215
+            groups=groups,
216
+            save_now=True,
217
+        )
218
+        workspace_api = WorkspaceApi(
219
+            current_user=user,
220
+            session=self.session,
221
+            config=self.app_config,
222
+        )
195
         workspace = workspace_api.create_workspace(
223
         workspace = workspace_api.create_workspace(
196
             'test workspace',
224
             'test workspace',
197
             save_now=True
225
             save_now=True
210
         transaction.commit()
238
         transaction.commit()
211
         # Refresh instances after commit
239
         # Refresh instances after commit
212
         user = uapi.get_one(uid)
240
         user = uapi.get_one(uid)
213
-        workspace_api = WorkspaceApi(current_user=user, session=self.session)
241
+        workspace_api = WorkspaceApi(
242
+            current_user=user,
243
+            session=self.session,
244
+            config=self.app_config,
245
+        )
214
         api = ContentApi(
246
         api = ContentApi(
215
             session=self.session,
247
             session=self.session,
216
             current_user=user,
248
             current_user=user,
231
 
263
 
232
         # Refresh instances after commit
264
         # Refresh instances after commit
233
         user = uapi.get_one(uid)
265
         user = uapi.get_one(uid)
234
-        workspace_api = WorkspaceApi(current_user=user, session=self.session)
266
+        workspace_api = WorkspaceApi(
267
+            current_user=user,
268
+            session=self.session,
269
+            config=self.app_config,
270
+        )
235
         workspace = workspace_api.get_one(wid)
271
         workspace = workspace_api.get_one(wid)
236
         api = ContentApi(
272
         api = ContentApi(
237
             current_user=user, 
273
             current_user=user, 
245
 
281
 
246
         # Refresh instances after commit
282
         # Refresh instances after commit
247
         user = uapi.get_one(uid)
283
         user = uapi.get_one(uid)
248
-        workspace_api = WorkspaceApi(current_user=user, session=self.session)
284
+        workspace_api = WorkspaceApi(
285
+            current_user=user,
286
+            session=self.session,
287
+            config=self.app_config,
288
+        )
249
         workspace = workspace_api.get_one(wid)
289
         workspace = workspace_api.get_one(wid)
250
         api = ContentApi(
290
         api = ContentApi(
251
             current_user=user,
291
             current_user=user,
269
             config=self.app_config,
309
             config=self.app_config,
270
             current_user=None,
310
             current_user=None,
271
         )
311
         )
272
-        group_api = GroupApi(current_user=None, session=self.session)
312
+        group_api = GroupApi(
313
+            current_user=None,
314
+            session=self.session,
315
+            config=self.app_config,
316
+        )
273
         groups = [group_api.get_one(Group.TIM_USER),
317
         groups = [group_api.get_one(Group.TIM_USER),
274
                   group_api.get_one(Group.TIM_MANAGER),
318
                   group_api.get_one(Group.TIM_MANAGER),
275
                   group_api.get_one(Group.TIM_ADMIN)]
319
                   group_api.get_one(Group.TIM_ADMIN)]
281
         )
325
         )
282
         workspace = WorkspaceApi(
326
         workspace = WorkspaceApi(
283
             current_user=user,
327
             current_user=user,
284
-            session=self.session
328
+            session=self.session,
329
+            config=self.app_config,
285
         ).create_workspace(
330
         ).create_workspace(
286
             'test workspace',
331
             'test workspace',
287
             save_now=True
332
             save_now=True
301
 
346
 
302
         # Refresh instances after commit
347
         # Refresh instances after commit
303
         user = uapi.get_one(uid)
348
         user = uapi.get_one(uid)
304
-        workspace_api = WorkspaceApi(current_user=user, session=self.session)
349
+        workspace_api = WorkspaceApi(
350
+            current_user=user,
351
+            session=self.session,
352
+            config=self.app_config,
353
+        )
305
         workspace = workspace_api.get_one(wid)
354
         workspace = workspace_api.get_one(wid)
306
         api = ContentApi(
355
         api = ContentApi(
307
             current_user=user, 
356
             current_user=user, 
326
             config=self.app_config,
375
             config=self.app_config,
327
             current_user=None,
376
             current_user=None,
328
         )
377
         )
329
-        group_api = GroupApi(current_user=None, session=self.session)
378
+        group_api = GroupApi(
379
+            current_user=None,
380
+            session=self.session,
381
+            config=self.app_config
382
+        )
330
         groups = [group_api.get_one(Group.TIM_USER),
383
         groups = [group_api.get_one(Group.TIM_USER),
331
                   group_api.get_one(Group.TIM_MANAGER),
384
                   group_api.get_one(Group.TIM_MANAGER),
332
                   group_api.get_one(Group.TIM_ADMIN)]
385
                   group_api.get_one(Group.TIM_ADMIN)]
335
                                         groups=groups, save_now=True)
388
                                         groups=groups, save_now=True)
336
         workspace = WorkspaceApi(
389
         workspace = WorkspaceApi(
337
             current_user=user,
390
             current_user=user,
338
-            session=self.session
391
+            session=self.session,
392
+            config=self.app_config
339
         ).create_workspace('test workspace', save_now=True)
393
         ).create_workspace('test workspace', save_now=True)
340
         api = ContentApi(
394
         api = ContentApi(
341
             current_user=user, 
395
             current_user=user, 
371
 
425
 
372
         # Refresh instances after commit
426
         # Refresh instances after commit
373
         user = uapi.get_one(uid)
427
         user = uapi.get_one(uid)
374
-        workspace_api = WorkspaceApi(current_user=user, session=self.session)
428
+        workspace_api = WorkspaceApi(
429
+            current_user=user,
430
+            session=self.session,
431
+            config=self.app_config,
432
+        )
375
         workspace = workspace_api.get_one(wid)
433
         workspace = workspace_api.get_one(wid)
376
         api = ContentApi(
434
         api = ContentApi(
377
             current_user=user,
435
             current_user=user,
394
         )
452
         )
395
         group_api = GroupApi(
453
         group_api = GroupApi(
396
             current_user=None,
454
             current_user=None,
397
-            session=self.session
455
+            session=self.session,
456
+            config=self.app_config,
398
         )
457
         )
399
         groups = [group_api.get_one(Group.TIM_USER),
458
         groups = [group_api.get_one(Group.TIM_USER),
400
                   group_api.get_one(Group.TIM_MANAGER),
459
                   group_api.get_one(Group.TIM_MANAGER),
405
 
464
 
406
         workspace = WorkspaceApi(
465
         workspace = WorkspaceApi(
407
             current_user=user,
466
             current_user=user,
408
-            session=self.session
467
+            session=self.session,
468
+            config=self.app_config,
409
         ).create_workspace(
469
         ).create_workspace(
410
             'test workspace',
470
             'test workspace',
411
             save_now=True
471
             save_now=True
432
         )
492
         )
433
         group_api = GroupApi(
493
         group_api = GroupApi(
434
             current_user=None,
494
             current_user=None,
435
-            session=self.session
495
+            session=self.session,
496
+            config=self.app_config,
436
         )
497
         )
437
         groups = [group_api.get_one(Group.TIM_USER),
498
         groups = [group_api.get_one(Group.TIM_USER),
438
                   group_api.get_one(Group.TIM_MANAGER),
499
                   group_api.get_one(Group.TIM_MANAGER),
443
 
504
 
444
         workspace = WorkspaceApi(
505
         workspace = WorkspaceApi(
445
             current_user=user,
506
             current_user=user,
446
-            session=self.session
507
+            session=self.session,
508
+            config=self.app_config,
447
         ).create_workspace(
509
         ).create_workspace(
448
             'test workspace',
510
             'test workspace',
449
             save_now=True
511
             save_now=True
474
         )
536
         )
475
         group_api = GroupApi(
537
         group_api = GroupApi(
476
             current_user=None,
538
             current_user=None,
477
-            session=self.session
539
+            session=self.session,
540
+            config=self.config,
478
         )
541
         )
479
         groups = [group_api.get_one(Group.TIM_USER),
542
         groups = [group_api.get_one(Group.TIM_USER),
480
                   group_api.get_one(Group.TIM_MANAGER),
543
                   group_api.get_one(Group.TIM_MANAGER),
485
 
548
 
486
         workspace = WorkspaceApi(
549
         workspace = WorkspaceApi(
487
             current_user=user,
550
             current_user=user,
488
-            session=self.session
551
+            session=self.session,
552
+            config=self.app_config,
489
         ).create_workspace(
553
         ).create_workspace(
490
             'test workspace',
554
             'test workspace',
491
             save_now=True
555
             save_now=True
516
         )
580
         )
517
         group_api = GroupApi(
581
         group_api = GroupApi(
518
             current_user=None,
582
             current_user=None,
519
-            session=self.session
583
+            session=self.session,
584
+            config=self.app_config
520
         )
585
         )
521
         groups = [group_api.get_one(Group.TIM_USER),
586
         groups = [group_api.get_one(Group.TIM_USER),
522
                   group_api.get_one(Group.TIM_MANAGER),
587
                   group_api.get_one(Group.TIM_MANAGER),
534
         )
599
         )
535
         workspace = WorkspaceApi(
600
         workspace = WorkspaceApi(
536
             current_user=user,
601
             current_user=user,
537
-            session=self.session
602
+            session=self.session,
603
+            config=self.app_config,
538
         ).create_workspace(
604
         ).create_workspace(
539
             'test workspace',
605
             'test workspace',
540
             save_now=True
606
             save_now=True
541
         )
607
         )
542
-        RoleApi(current_user=user, session=self.session).create_one(
608
+        RoleApi(
609
+            current_user=user,
610
+            session=self.session,
611
+            config=self.app_config,
612
+        ).create_one(
543
             user2,
613
             user2,
544
             workspace,
614
             workspace,
545
             UserRoleInWorkspace.WORKSPACE_MANAGER,
615
             UserRoleInWorkspace.WORKSPACE_MANAGER,
581
         workspace2 = WorkspaceApi(
651
         workspace2 = WorkspaceApi(
582
             current_user=user2,
652
             current_user=user2,
583
             session=self.session,
653
             session=self.session,
654
+            config=self.app_config,
584
         ).create_workspace(
655
         ).create_workspace(
585
             'test workspace2',
656
             'test workspace2',
586
             save_now=True
657
             save_now=True
628
         )
699
         )
629
         group_api = GroupApi(
700
         group_api = GroupApi(
630
             current_user=None,
701
             current_user=None,
631
-            session=self.session
702
+            session=self.session,
703
+            config=self.app_config,
632
         )
704
         )
633
         groups = [group_api.get_one(Group.TIM_USER),
705
         groups = [group_api.get_one(Group.TIM_USER),
634
                   group_api.get_one(Group.TIM_MANAGER),
706
                   group_api.get_one(Group.TIM_MANAGER),
646
         )
718
         )
647
         workspace = WorkspaceApi(
719
         workspace = WorkspaceApi(
648
             current_user=user,
720
             current_user=user,
649
-            session=self.session
721
+            session=self.session,
722
+            config=self.app_config,
650
         ).create_workspace(
723
         ).create_workspace(
651
             'test workspace',
724
             'test workspace',
652
             save_now=True
725
             save_now=True
653
         )
726
         )
654
-        RoleApi(current_user=user, session=self.session).create_one(
727
+        RoleApi(
728
+            current_user=user,
729
+            session=self.session,
730
+            config=self.app_config,
731
+        ).create_one(
655
             user2,
732
             user2,
656
             workspace,
733
             workspace,
657
             UserRoleInWorkspace.WORKSPACE_MANAGER,
734
             UserRoleInWorkspace.WORKSPACE_MANAGER,
692
         )
769
         )
693
         workspace2 = WorkspaceApi(
770
         workspace2 = WorkspaceApi(
694
             current_user=user2,
771
             current_user=user2,
695
-            session=self.session
772
+            session=self.session,
773
+            config=self.app_config,
696
         ).create_workspace(
774
         ).create_workspace(
697
             'test workspace2',
775
             'test workspace2',
698
             save_now=True
776
             save_now=True
738
         )
816
         )
739
         group_api = GroupApi(
817
         group_api = GroupApi(
740
             current_user=None,
818
             current_user=None,
741
-            session=self.session
819
+            session=self.session,
820
+            config=self.app_config,
742
         )
821
         )
743
         groups = [group_api.get_one(Group.TIM_USER),
822
         groups = [group_api.get_one(Group.TIM_USER),
744
                   group_api.get_one(Group.TIM_MANAGER),
823
                   group_api.get_one(Group.TIM_MANAGER),
756
         )
835
         )
757
         workspace = WorkspaceApi(
836
         workspace = WorkspaceApi(
758
             current_user=user,
837
             current_user=user,
759
-            session=self.session
838
+            session=self.session,
839
+            config=self.app_config,
760
         ).create_workspace(
840
         ).create_workspace(
761
             'test workspace',
841
             'test workspace',
762
             save_now=True
842
             save_now=True
763
         )
843
         )
764
-        RoleApi(current_user=user, session=self.session).create_one(
844
+        RoleApi(
845
+            current_user=user,
846
+            session=self.session,
847
+            config=self.app_config,
848
+        ).create_one(
765
             user2, workspace,
849
             user2, workspace,
766
             UserRoleInWorkspace.WORKSPACE_MANAGER,
850
             UserRoleInWorkspace.WORKSPACE_MANAGER,
767
             with_notif=False
851
             with_notif=False
837
         )
921
         )
838
         group_api = GroupApi(
922
         group_api = GroupApi(
839
             current_user=None,
923
             current_user=None,
840
-            session=self.session
924
+            session=self.session,
925
+            config=self.app_config,
841
         )
926
         )
842
         groups = [group_api.get_one(Group.TIM_USER),
927
         groups = [group_api.get_one(Group.TIM_USER),
843
                   group_api.get_one(Group.TIM_MANAGER),
928
                   group_api.get_one(Group.TIM_MANAGER),
851
         wapi = WorkspaceApi(
936
         wapi = WorkspaceApi(
852
             current_user=user_a,
937
             current_user=user_a,
853
             session=self.session,
938
             session=self.session,
939
+            config=self.app_config,
854
         )
940
         )
855
         workspace1 = wapi.create_workspace(
941
         workspace1 = wapi.create_workspace(
856
             'test workspace n°1',
942
             'test workspace n°1',
862
         role_api1 = RoleApi(
948
         role_api1 = RoleApi(
863
             current_user=user_a,
949
             current_user=user_a,
864
             session=self.session,
950
             session=self.session,
951
+            config=self.app_config,
865
         )
952
         )
866
         role_api1.create_one(
953
         role_api1.create_one(
867
             user_b,
954
             user_b,
873
         role_api2 = RoleApi(
960
         role_api2 = RoleApi(
874
             current_user=user_b,
961
             current_user=user_b,
875
             session=self.session,
962
             session=self.session,
963
+            config=self.app_config,
876
         )
964
         )
877
         role_api2.create_one(user_b, workspace2, UserRoleInWorkspace.READER,
965
         role_api2.create_one(user_b, workspace2, UserRoleInWorkspace.READER,
878
                              False)
966
                              False)
940
         )
1028
         )
941
         group_api = GroupApi(
1029
         group_api = GroupApi(
942
             current_user=None,
1030
             current_user=None,
943
-            session=self.session
1031
+            session=self.session,
1032
+            config = self.app_config,
944
         )
1033
         )
945
         groups = [group_api.get_one(Group.TIM_USER),
1034
         groups = [group_api.get_one(Group.TIM_USER),
946
                   group_api.get_one(Group.TIM_MANAGER),
1035
                   group_api.get_one(Group.TIM_MANAGER),
957
             save_now=True
1046
             save_now=True
958
         )
1047
         )
959
 
1048
 
960
-        wapi = WorkspaceApi(current_user=user_a, session=self.session)
1049
+        wapi = WorkspaceApi(
1050
+            current_user=user_a,
1051
+            session=self.session,
1052
+            config=self.app_config,
1053
+        )
961
         workspace_api = WorkspaceApi(
1054
         workspace_api = WorkspaceApi(
962
             current_user=user_a,
1055
             current_user=user_a,
963
-            session=self.session
1056
+            session=self.session,
1057
+            config=self.app_config,
964
         )
1058
         )
965
         workspace = wapi.create_workspace(
1059
         workspace = wapi.create_workspace(
966
             'test workspace',
1060
             'test workspace',
969
         role_api = RoleApi(
1063
         role_api = RoleApi(
970
             current_user=user_a,
1064
             current_user=user_a,
971
             session=self.session,
1065
             session=self.session,
1066
+            config=self.app_config,
972
         )
1067
         )
973
         role_api.create_one(
1068
         role_api.create_one(
974
             user_b,
1069
             user_b,
1004
             config=self.app_config,
1099
             config=self.app_config,
1005
             current_user=None,
1100
             current_user=None,
1006
         )
1101
         )
1007
-        group_api = GroupApi(current_user=None, session=self.session)
1102
+        group_api = GroupApi(
1103
+            current_user=None,
1104
+            session=self.session,
1105
+            config=self.app_config,
1106
+        )
1008
         groups = [group_api.get_one(Group.TIM_USER),
1107
         groups = [group_api.get_one(Group.TIM_USER),
1009
                   group_api.get_one(Group.TIM_MANAGER),
1108
                   group_api.get_one(Group.TIM_MANAGER),
1010
                   group_api.get_one(Group.TIM_ADMIN)]
1109
                   group_api.get_one(Group.TIM_ADMIN)]
1023
         wapi = WorkspaceApi(
1122
         wapi = WorkspaceApi(
1024
             current_user=user_a,
1123
             current_user=user_a,
1025
             session=self.session,
1124
             session=self.session,
1125
+            config=self.app_config,
1026
         )
1126
         )
1027
         workspace = wapi.create_workspace(
1127
         workspace = wapi.create_workspace(
1028
             'test workspace',
1128
             'test workspace',
1031
         role_api = RoleApi(
1131
         role_api = RoleApi(
1032
             current_user=user_a,
1132
             current_user=user_a,
1033
             session=self.session,
1133
             session=self.session,
1134
+            config=self.app_config,
1034
         )
1135
         )
1035
         role_api.create_one(
1136
         role_api.create_one(
1036
             user_b,
1137
             user_b,
1097
             config=self.app_config,
1198
             config=self.app_config,
1098
             current_user=None,
1199
             current_user=None,
1099
         )
1200
         )
1100
-        group_api = GroupApi(current_user=None, session=self.session)
1201
+        group_api = GroupApi(
1202
+            current_user=None,
1203
+            session=self.session,
1204
+            config=self.app_config,
1205
+        )
1101
         groups = [group_api.get_one(Group.TIM_USER),
1206
         groups = [group_api.get_one(Group.TIM_USER),
1102
                   group_api.get_one(Group.TIM_MANAGER),
1207
                   group_api.get_one(Group.TIM_MANAGER),
1103
                   group_api.get_one(Group.TIM_ADMIN)]
1208
                   group_api.get_one(Group.TIM_ADMIN)]
1108
             save_now=True
1213
             save_now=True
1109
         )
1214
         )
1110
 
1215
 
1111
-        workspace_api = WorkspaceApi(current_user=user1, session=self.session)
1216
+        workspace_api = WorkspaceApi(
1217
+            current_user=user1,
1218
+            session=self.session,
1219
+            config=self.app_config,
1220
+        )
1112
         workspace = workspace_api.create_workspace(
1221
         workspace = workspace_api.create_workspace(
1113
             'test workspace',
1222
             'test workspace',
1114
             save_now=True
1223
             save_now=True
1121
 
1230
 
1122
         RoleApi(
1231
         RoleApi(
1123
             current_user=user1,
1232
             current_user=user1,
1124
-            session=self.session
1233
+            session=self.session,
1234
+            config=self.app_config,
1125
         ).create_one(
1235
         ).create_one(
1126
             user2,
1236
             user2,
1127
             workspace,
1237
             workspace,
1152
         user1 = uapi.get_one(u1id)
1262
         user1 = uapi.get_one(u1id)
1153
         workspace = WorkspaceApi(
1263
         workspace = WorkspaceApi(
1154
             current_user=user1,
1264
             current_user=user1,
1155
-            session=self.session
1265
+            session=self.session,
1266
+            config=self.app_config,
1156
         ).get_one(wid)
1267
         ).get_one(wid)
1157
         api = ContentApi(
1268
         api = ContentApi(
1158
             current_user=user1,
1269
             current_user=user1,
1193
         workspace = WorkspaceApi(
1304
         workspace = WorkspaceApi(
1194
             current_user=user1,
1305
             current_user=user1,
1195
             session=self.session,
1306
             session=self.session,
1307
+            config=self.app_config,
1196
         ).get_one(wid)
1308
         ).get_one(wid)
1197
         api = ContentApi(
1309
         api = ContentApi(
1198
             current_user=user1,
1310
             current_user=user1,
1216
         )
1328
         )
1217
         group_api = GroupApi(
1329
         group_api = GroupApi(
1218
             current_user=None,
1330
             current_user=None,
1219
-            session=self.session
1331
+            session=self.session,
1332
+            config = self.app_config,
1220
         )
1333
         )
1221
         groups = [group_api.get_one(Group.TIM_USER),
1334
         groups = [group_api.get_one(Group.TIM_USER),
1222
                   group_api.get_one(Group.TIM_MANAGER),
1335
                   group_api.get_one(Group.TIM_MANAGER),
1231
         workspace = WorkspaceApi(
1344
         workspace = WorkspaceApi(
1232
             current_user=user1,
1345
             current_user=user1,
1233
             session=self.session,
1346
             session=self.session,
1347
+            config=self.app_config,
1234
         ).create_workspace(
1348
         ).create_workspace(
1235
             'test workspace',
1349
             'test workspace',
1236
             save_now=True
1350
             save_now=True
1241
 
1355
 
1242
         RoleApi(
1356
         RoleApi(
1243
             current_user=user1,
1357
             current_user=user1,
1244
-            session=self.session
1358
+            session=self.session,
1359
+            config=self.app_config,
1245
         ).create_one(
1360
         ).create_one(
1246
             user2,
1361
             user2,
1247
             workspace,
1362
             workspace,
1293
         )
1408
         )
1294
         group_api = GroupApi(
1409
         group_api = GroupApi(
1295
             current_user=None,
1410
             current_user=None,
1296
-            session=self.session
1411
+            session=self.session,
1412
+            config=self.app_config,
1297
         )
1413
         )
1298
         groups = [group_api.get_one(Group.TIM_USER),
1414
         groups = [group_api.get_one(Group.TIM_USER),
1299
                   group_api.get_one(Group.TIM_MANAGER),
1415
                   group_api.get_one(Group.TIM_MANAGER),
1305
             save_now=True
1421
             save_now=True
1306
         )
1422
         )
1307
 
1423
 
1308
-        workspace_api = WorkspaceApi(current_user=user1, session=self.session)
1424
+        workspace_api = WorkspaceApi(
1425
+            current_user=user1,
1426
+            session=self.session,
1427
+            config=self.app_config,
1428
+        )
1309
         workspace = workspace_api.create_workspace(
1429
         workspace = workspace_api.create_workspace(
1310
             'test workspace',
1430
             'test workspace',
1311
             save_now=True
1431
             save_now=True
1318
         RoleApi(
1438
         RoleApi(
1319
             current_user=user1,
1439
             current_user=user1,
1320
             session=self.session,
1440
             session=self.session,
1441
+            config=self.app_config,
1321
         ).create_one(
1442
         ).create_one(
1322
             user2,
1443
             user2,
1323
             workspace,
1444
             workspace,
1345
 
1466
 
1346
         # Refresh instances after commit
1467
         # Refresh instances after commit
1347
         user1 = uapi.get_one(u1id)
1468
         user1 = uapi.get_one(u1id)
1348
-        workspace_api2 = WorkspaceApi(current_user=user1, session=self.session)
1469
+        workspace_api2 = WorkspaceApi(
1470
+            current_user=user1,
1471
+            session=self.session,
1472
+            config=self.app_config,
1473
+        )
1349
         workspace = workspace_api2.get_one(wid)
1474
         workspace = workspace_api2.get_one(wid)
1350
         api = ContentApi(
1475
         api = ContentApi(
1351
             current_user=user1,
1476
             current_user=user1,
1387
         workspace = WorkspaceApi(
1512
         workspace = WorkspaceApi(
1388
             current_user=user1,
1513
             current_user=user1,
1389
             session=self.session,
1514
             session=self.session,
1515
+            config=self.app_config,
1390
         ).get_one(wid)
1516
         ).get_one(wid)
1391
 
1517
 
1392
         updated = api.get_one(pcid, ContentType.Any, workspace)
1518
         updated = api.get_one(pcid, ContentType.Any, workspace)
1407
         group_api = GroupApi(
1533
         group_api = GroupApi(
1408
             current_user=None,
1534
             current_user=None,
1409
             session=self.session,
1535
             session=self.session,
1536
+            config=self.app_config,
1410
         )
1537
         )
1411
         groups = [group_api.get_one(Group.TIM_USER),
1538
         groups = [group_api.get_one(Group.TIM_USER),
1412
                   group_api.get_one(Group.TIM_MANAGER),
1539
                   group_api.get_one(Group.TIM_MANAGER),
1418
             save_now=True,
1545
             save_now=True,
1419
         )
1546
         )
1420
 
1547
 
1421
-        workspace_api = WorkspaceApi(current_user=user1, session=self.session)
1548
+        workspace_api = WorkspaceApi(
1549
+            current_user=user1,
1550
+            session=self.session,
1551
+            config=self.app_config,
1552
+        )
1422
         workspace = workspace_api.create_workspace(
1553
         workspace = workspace_api.create_workspace(
1423
             'test workspace',
1554
             'test workspace',
1424
             save_now=True
1555
             save_now=True
1430
         RoleApi(
1561
         RoleApi(
1431
             current_user=user1,
1562
             current_user=user1,
1432
             session=self.session,
1563
             session=self.session,
1564
+            config=self.app_config,
1433
         ).create_one(
1565
         ).create_one(
1434
             user2,
1566
             user2,
1435
             workspace,
1567
             workspace,
1485
             config=self.app_config,
1617
             config=self.app_config,
1486
             current_user=None,
1618
             current_user=None,
1487
         )
1619
         )
1488
-        group_api = GroupApi(current_user=None, session=self.session)
1620
+        group_api = GroupApi(
1621
+            current_user=None,
1622
+            session=self.session,
1623
+            config=self.app_config,
1624
+        )
1489
         groups = [group_api.get_one(Group.TIM_USER),
1625
         groups = [group_api.get_one(Group.TIM_USER),
1490
                   group_api.get_one(Group.TIM_MANAGER),
1626
                   group_api.get_one(Group.TIM_MANAGER),
1491
                   group_api.get_one(Group.TIM_ADMIN)]
1627
                   group_api.get_one(Group.TIM_ADMIN)]
1497
         )
1633
         )
1498
         u1id = user1.user_id
1634
         u1id = user1.user_id
1499
 
1635
 
1500
-        workspace_api = WorkspaceApi(current_user=user1, session=self.session)
1636
+        workspace_api = WorkspaceApi(
1637
+            current_user=user1,
1638
+            session=self.session,
1639
+            config=self.app_config,
1640
+        )
1501
         workspace = workspace_api.create_workspace(
1641
         workspace = workspace_api.create_workspace(
1502
             'test workspace',
1642
             'test workspace',
1503
             save_now=True
1643
             save_now=True
1509
 
1649
 
1510
         RoleApi(
1650
         RoleApi(
1511
             current_user=user1,
1651
             current_user=user1,
1512
-            session=self.session
1652
+            session=self.session,
1653
+            config=self.app_config,
1513
         ).create_one(
1654
         ).create_one(
1514
             user2,
1655
             user2,
1515
             workspace,
1656
             workspace,
1545
         ).get_one(u1id)
1686
         ).get_one(u1id)
1546
         workspace = WorkspaceApi(
1687
         workspace = WorkspaceApi(
1547
             current_user=user1,
1688
             current_user=user1,
1548
-            session=self.session
1689
+            session=self.session,
1690
+            config=self.app_config,
1549
         ).get_one(wid)
1691
         ).get_one(wid)
1550
 
1692
 
1551
         content = api.get_one(pcid, ContentType.Any, workspace)
1693
         content = api.get_one(pcid, ContentType.Any, workspace)
1583
         workspace = WorkspaceApi(
1725
         workspace = WorkspaceApi(
1584
             current_user=user1,
1726
             current_user=user1,
1585
             session=self.session,
1727
             session=self.session,
1728
+            config=self.app_config,
1586
         ).get_one(wid)
1729
         ).get_one(wid)
1587
         u2 = UserApi(
1730
         u2 = UserApi(
1588
             current_user=None,
1731
             current_user=None,
1632
         )
1775
         )
1633
         group_api = GroupApi(
1776
         group_api = GroupApi(
1634
             current_user=None,
1777
             current_user=None,
1635
-            session=self.session
1778
+            session=self.session,
1779
+            config=self.app_config,
1636
         )
1780
         )
1637
         groups = [group_api.get_one(Group.TIM_USER),
1781
         groups = [group_api.get_one(Group.TIM_USER),
1638
                   group_api.get_one(Group.TIM_MANAGER),
1782
                   group_api.get_one(Group.TIM_MANAGER),
1645
         )
1789
         )
1646
         u1id = user1.user_id
1790
         u1id = user1.user_id
1647
 
1791
 
1648
-        workspace_api = WorkspaceApi(current_user=user1, session=self.session)
1792
+        workspace_api = WorkspaceApi(
1793
+            current_user=user1,
1794
+            session=self.session,
1795
+            config=self.app_config,
1796
+        )
1649
         workspace = workspace_api.create_workspace(
1797
         workspace = workspace_api.create_workspace(
1650
             'test workspace',
1798
             'test workspace',
1651
             save_now=True
1799
             save_now=True
1657
 
1805
 
1658
         RoleApi(
1806
         RoleApi(
1659
             current_user=user1,
1807
             current_user=user1,
1660
-            session=self.session
1808
+            session=self.session,
1809
+            config=self.app_config,
1661
         ).create_one(
1810
         ).create_one(
1662
             user2,
1811
             user2,
1663
             workspace,
1812
             workspace,
1692
         workspace = WorkspaceApi(
1841
         workspace = WorkspaceApi(
1693
             current_user=user1,
1842
             current_user=user1,
1694
             session=self.session,
1843
             session=self.session,
1844
+            config=self.app_config,
1695
         ).get_one(wid)
1845
         ).get_one(wid)
1696
 
1846
 
1697
         content = api.get_one(pcid, ContentType.Any, workspace)
1847
         content = api.get_one(pcid, ContentType.Any, workspace)
1729
         workspace = WorkspaceApi(
1879
         workspace = WorkspaceApi(
1730
             current_user=user1,
1880
             current_user=user1,
1731
             session=self.session,
1881
             session=self.session,
1882
+            config=self.app_config,
1732
         ).get_one(wid)
1883
         ).get_one(wid)
1733
         # show archived is used at the top end of the test
1884
         # show archived is used at the top end of the test
1734
         api = ContentApi(
1885
         api = ContentApi(
1782
         group_api = GroupApi(
1933
         group_api = GroupApi(
1783
             current_user=None,
1934
             current_user=None,
1784
             session=self.session,
1935
             session=self.session,
1936
+            config=self.app_config,
1785
         )
1937
         )
1786
         groups = [group_api.get_one(Group.TIM_USER),
1938
         groups = [group_api.get_one(Group.TIM_USER),
1787
                   group_api.get_one(Group.TIM_MANAGER),
1939
                   group_api.get_one(Group.TIM_MANAGER),
1792
 
1944
 
1793
         workspace = WorkspaceApi(
1945
         workspace = WorkspaceApi(
1794
             current_user=user,
1946
             current_user=user,
1795
-            session=self.session
1947
+            session=self.session,
1948
+            config=self.app_config,
1796
         ).create_workspace(
1949
         ).create_workspace(
1797
             'test workspace',
1950
             'test workspace',
1798
             save_now=True
1951
             save_now=True
1802
             current_user=user, 
1955
             current_user=user, 
1803
             session=self.session,
1956
             session=self.session,
1804
             config=self.app_config,
1957
             config=self.app_config,
1805
-
1806
         )
1958
         )
1807
         a = api.create(ContentType.Folder, workspace, None,
1959
         a = api.create(ContentType.Folder, workspace, None,
1808
                        'this is randomized folder', True)
1960
                        'this is randomized folder', True)
1837
         group_api = GroupApi(
1989
         group_api = GroupApi(
1838
             current_user=None,
1990
             current_user=None,
1839
             session=self.session,
1991
             session=self.session,
1992
+            config=self.app_config,
1840
         )
1993
         )
1841
         groups = [group_api.get_one(Group.TIM_USER),
1994
         groups = [group_api.get_one(Group.TIM_USER),
1842
                   group_api.get_one(Group.TIM_MANAGER),
1995
                   group_api.get_one(Group.TIM_MANAGER),
1847
 
2000
 
1848
         workspace = WorkspaceApi(
2001
         workspace = WorkspaceApi(
1849
             current_user=user,
2002
             current_user=user,
1850
-            session=self.session
2003
+            session=self.session,
2004
+            config=self.app_config,
1851
         ).create_workspace(
2005
         ).create_workspace(
1852
             'test workspace',
2006
             'test workspace',
1853
             save_now=True,
2007
             save_now=True,
1888
             config=self.app_config,
2042
             config=self.app_config,
1889
             current_user=None,
2043
             current_user=None,
1890
         )
2044
         )
1891
-        group_api = GroupApi(current_user=None, session=self.session)
2045
+        group_api = GroupApi(
2046
+            current_user=None,
2047
+            session=self.session,
2048
+            config=self.app_config,
2049
+        )
1892
         groups = [group_api.get_one(Group.TIM_USER),
2050
         groups = [group_api.get_one(Group.TIM_USER),
1893
                   group_api.get_one(Group.TIM_MANAGER),
2051
                   group_api.get_one(Group.TIM_MANAGER),
1894
                   group_api.get_one(Group.TIM_ADMIN)]
2052
                   group_api.get_one(Group.TIM_ADMIN)]
1898
 
2056
 
1899
         workspace = WorkspaceApi(
2057
         workspace = WorkspaceApi(
1900
             current_user=user,
2058
             current_user=user,
1901
-            session=self.session
2059
+            session=self.session,
2060
+            config=self.app_config,
1902
         ).create_workspace('test workspace', save_now=True)
2061
         ).create_workspace('test workspace', save_now=True)
1903
 
2062
 
1904
         api = ContentApi(
2063
         api = ContentApi(
2032
         bob_workspace = WorkspaceApi(
2191
         bob_workspace = WorkspaceApi(
2033
             current_user=bob,
2192
             current_user=bob,
2034
             session=self.session,
2193
             session=self.session,
2194
+            config=self.app_config,
2035
         ).create_workspace(
2195
         ).create_workspace(
2036
             'bob_workspace',
2196
             'bob_workspace',
2037
             save_now=True,
2197
             save_now=True,
2039
         admin_workspace = WorkspaceApi(
2199
         admin_workspace = WorkspaceApi(
2040
             current_user=admin,
2200
             current_user=admin,
2041
             session=self.session,
2201
             session=self.session,
2202
+            config=self.app_config,
2042
         ).create_workspace(
2203
         ).create_workspace(
2043
             'admin_workspace',
2204
             'admin_workspace',
2044
             save_now=True,
2205
             save_now=True,

+ 5 - 0
tracim/tests/library/test_group_api.py Ver arquivo

18
         api = GroupApi(
18
         api = GroupApi(
19
             current_user=None,
19
             current_user=None,
20
             session=self.session,
20
             session=self.session,
21
+            config=self.app_config,
21
         )
22
         )
22
         group = api.get_one(1)
23
         group = api.get_one(1)
23
         assert group.group_id == 1
24
         assert group.group_id == 1
30
         api = GroupApi(
31
         api = GroupApi(
31
             current_user=None,
32
             current_user=None,
32
             session=self.session,
33
             session=self.session,
34
+            config=self.app_config,
33
         )
35
         )
34
         with pytest.raises(GroupNotExist):
36
         with pytest.raises(GroupNotExist):
35
             group = api.get_one(10)
37
             group = api.get_one(10)
41
         api = GroupApi(
43
         api = GroupApi(
42
             current_user=None,
44
             current_user=None,
43
             session=self.session,
45
             session=self.session,
46
+            config=self.app_config,
44
         )
47
         )
45
         group = api.get_one_with_name('administrators')
48
         group = api.get_one_with_name('administrators')
46
         assert group.group_id == 3
49
         assert group.group_id == 3
53
         api = GroupApi(
56
         api = GroupApi(
54
             current_user=None,
57
             current_user=None,
55
             session=self.session,
58
             session=self.session,
59
+            config=self.app_config,
56
         )
60
         )
57
         with pytest.raises(GroupNotExist):
61
         with pytest.raises(GroupNotExist):
58
             group = api.get_one_with_name('unknown_group')
62
             group = api.get_one_with_name('unknown_group')
64
         api = GroupApi(
68
         api = GroupApi(
65
             current_user=None,
69
             current_user=None,
66
             session=self.session,
70
             session=self.session,
71
+            config=self.app_config,
67
         )
72
         )
68
         groups = api.get_all()
73
         groups = api.get_all()
69
         assert ['users', 'managers', 'administrators'] == [group.group_name for group in groups]  # nopep8
74
         assert ['users', 'managers', 'administrators'] == [group.group_name for group in groups]  # nopep8

+ 2 - 2
tracim/tests/library/test_user_api.py Ver arquivo

91
             session=self.session,
91
             session=self.session,
92
             config=self.config,
92
             config=self.config,
93
         )
93
         )
94
-        with pytest.raises(NoResultFound):
94
+        with pytest.raises(UserNotExist):
95
             api.get_one_by_email('unknown')
95
             api.get_one_by_email('unknown')
96
 
96
 
97
     def test_unit__get_all__ok__nominal_case(self):
97
     def test_unit__get_all__ok__nominal_case(self):
187
             config=self.config,
187
             config=self.config,
188
         )
188
         )
189
         with pytest.raises(AuthenticationFailed):
189
         with pytest.raises(AuthenticationFailed):
190
-            api.authenticate_user('unknown_user', 'wrong_password')
190
+            api.authenticate_user('admin@admin.admin', 'wrong_password')

+ 8 - 2
tracim/tests/library/test_workspace.py Ver arquivo

44
             .filter(User.email == 'admin@admin.admin').one()
44
             .filter(User.email == 'admin@admin.admin').one()
45
         wapi = WorkspaceApi(
45
         wapi = WorkspaceApi(
46
             session=self.session,
46
             session=self.session,
47
+            config=self.app_config,
47
             current_user=admin,
48
             current_user=admin,
48
         )
49
         )
49
         w = wapi.create_workspace(label='workspace w', save_now=True)
50
         w = wapi.create_workspace(label='workspace w', save_now=True)
57
         rapi = RoleApi(
58
         rapi = RoleApi(
58
             session=self.session,
59
             session=self.session,
59
             current_user=admin,
60
             current_user=admin,
61
+            config=self.app_config,
60
         )
62
         )
61
         r = rapi.create_one(u, w, UserRoleInWorkspace.READER, with_notif=True)
63
         r = rapi.create_one(u, w, UserRoleInWorkspace.READER, with_notif=True)
62
         eq_([r, ], wapi.get_notifiable_roles(workspace=w))
64
         eq_([r, ], wapi.get_notifiable_roles(workspace=w))
75
         wapi = WorkspaceApi(
77
         wapi = WorkspaceApi(
76
             session=self.session,
78
             session=self.session,
77
             current_user=admin,
79
             current_user=admin,
80
+            config=self.app_config,
78
         )
81
         )
79
         eq_([], wapi.get_all_manageable())
82
         eq_([], wapi.get_all_manageable())
80
         # Checks an admin gets all workspaces.
83
         # Checks an admin gets all workspaces.
87
         gapi = GroupApi(
90
         gapi = GroupApi(
88
             session=self.session,
91
             session=self.session,
89
             current_user=None,
92
             current_user=None,
93
+            config=self.app_config,
90
         )
94
         )
91
         u = uapi.create_minimal_user('u.s@e.r', [gapi.get_one(Group.TIM_USER)], True)
95
         u = uapi.create_minimal_user('u.s@e.r', [gapi.get_one(Group.TIM_USER)], True)
92
         wapi = WorkspaceApi(
96
         wapi = WorkspaceApi(
93
             session=self.session,
97
             session=self.session,
94
-            current_user=u
98
+            current_user=u,
99
+            config=self.app_config,
95
         )
100
         )
96
         rapi = RoleApi(
101
         rapi = RoleApi(
97
             session=self.session,
102
             session=self.session,
98
-            current_user=u
103
+            current_user=u,
104
+            config=self.app_config,
99
         )
105
         )
100
         rapi.create_one(u, w4, UserRoleInWorkspace.READER, False)
106
         rapi.create_one(u, w4, UserRoleInWorkspace.READER, False)
101
         rapi.create_one(u, w3, UserRoleInWorkspace.CONTRIBUTOR, False)
107
         rapi.create_one(u, w3, UserRoleInWorkspace.CONTRIBUTOR, False)

+ 0 - 0
tracim/views/core_api/__init__.py Ver arquivo


+ 68 - 3
tracim/views/core_api/schemas.py Ver arquivo

1
 # coding=utf-8
1
 # coding=utf-8
2
 import marshmallow
2
 import marshmallow
3
 from marshmallow import post_load
3
 from marshmallow import post_load
4
+from marshmallow.validate import OneOf
4
 
5
 
5
-from tracim.models.context_models import LoginCredentials, UserInContext
6
+from tracim.models.auth import Profile
7
+from tracim.models.context_models import LoginCredentials
8
+from tracim.models.data import UserRoleInWorkspace
6
 
9
 
7
 
10
 
8
 class ProfileSchema(marshmallow.Schema):
11
 class ProfileSchema(marshmallow.Schema):
9
-    id = marshmallow.fields.Int(dump_only=True)
10
-    slug = marshmallow.fields.String(attribute='name')
12
+    id = marshmallow.fields.Int(dump_only=True, validate=OneOf(Profile._IDS))
13
+    slug = marshmallow.fields.String(attribute='name', validate=OneOf(Profile._NAME))
11
 
14
 
12
 
15
 
13
 class UserSchema(marshmallow.Schema):
16
 class UserSchema(marshmallow.Schema):
32
     )
35
     )
33
 
36
 
34
 
37
 
38
+class UserIdPathSchema(marshmallow.Schema):
39
+    user_id = marshmallow.fields.Int()
40
+
41
+
42
+class WorkspaceIdPathSchema(marshmallow.Schema):
43
+    workspace_id = marshmallow.fields.Int()
44
+
45
+
35
 class BasicAuthSchema(marshmallow.Schema):
46
 class BasicAuthSchema(marshmallow.Schema):
36
 
47
 
37
     email = marshmallow.fields.Email(required=True)
48
     email = marshmallow.fields.Email(required=True)
48
 
59
 
49
 class NoContentSchema(marshmallow.Schema):
60
 class NoContentSchema(marshmallow.Schema):
50
     pass
61
     pass
62
+
63
+
64
+class WorkspaceMenuEntrySchema(marshmallow.Schema):
65
+    slug = marshmallow.fields.String()
66
+    label = marshmallow.fields.String()
67
+    route = marshmallow.fields.String()
68
+    hexcolor = marshmallow.fields.String()
69
+    icon = marshmallow.fields.String()
70
+
71
+
72
+class WorkspaceSchema(marshmallow.Schema):
73
+    id = marshmallow.fields.Int()
74
+    slug = marshmallow.fields.String()
75
+    label = marshmallow.fields.String()
76
+    description = marshmallow.fields.String()
77
+    sidebar_entries = marshmallow.fields.Nested(
78
+        WorkspaceMenuEntrySchema,
79
+        many=True,
80
+    )
81
+
82
+
83
+class WorkspaceDigestSchema(marshmallow.Schema):
84
+    id = marshmallow.fields.Int()
85
+    label = marshmallow.fields.String()
86
+    sidebar_entries = marshmallow.fields.Nested(
87
+        WorkspaceMenuEntrySchema,
88
+        many=True,
89
+    )
90
+
91
+
92
+class WorkspaceMemberSchema(marshmallow.Schema):
93
+    role_id = marshmallow.fields.Int(validate=OneOf(UserRoleInWorkspace.get_all_role_values()))  # nopep8
94
+    role_slug = marshmallow.fields.String(validate=OneOf(UserRoleInWorkspace.get_all_role_slug()))  # nopep8
95
+    user_id = marshmallow.fields.Int()
96
+    workspace_id = marshmallow.fields.Int()
97
+    user = marshmallow.fields.Nested(
98
+        UserSchema(only=('display_name', 'avatar_url'))
99
+    )
100
+
101
+
102
+class ApplicationConfigSchema(marshmallow.Schema):
103
+    pass
104
+    #  TODO - G.M - 24-05-2018 - Set this
105
+
106
+
107
+class ApplicationSchema(marshmallow.Schema):
108
+    label = marshmallow.fields.String()
109
+    slug = marshmallow.fields.String()
110
+    icon = marshmallow.fields.String()
111
+    hexcolor = marshmallow.fields.String()
112
+    is_active = marshmallow.fields.Boolean()
113
+    config = marshmallow.fields.Nested(
114
+        ApplicationConfigSchema,
115
+    )

+ 42 - 0
tracim/views/core_api/system_controller.py Ver arquivo

1
+# coding=utf-8
2
+from pyramid.config import Configurator
3
+
4
+from tracim.exceptions import NotAuthentificated, InsufficientUserProfile
5
+from tracim.lib.utils.authorization import require_profile
6
+from tracim.models import Group
7
+from tracim.models.applications import applications
8
+
9
+try:  # Python 3.5+
10
+    from http import HTTPStatus
11
+except ImportError:
12
+    from http import client as HTTPStatus
13
+
14
+from tracim import TracimRequest
15
+from tracim.extensions import hapic
16
+from tracim.views.controllers import Controller
17
+from tracim.views.core_api.schemas import ApplicationSchema
18
+
19
+
20
+class SystemController(Controller):
21
+
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)
26
+    @hapic.output_body(ApplicationSchema(many=True),)
27
+    def applications(self, context, request: TracimRequest, hapic_data=None):
28
+        """
29
+        Get list of alls applications installed in this tracim instance.
30
+        """
31
+        return applications
32
+
33
+    def bind(self, configurator: Configurator) -> None:
34
+        """
35
+        Create all routes and views using pyramid configurator
36
+        for this controller
37
+        """
38
+
39
+        # Applications
40
+        configurator.add_route('applications', '/system/applications', request_method='GET')  # nopep8
41
+        configurator.add_view(self.applications, route_name='applications')
42
+

+ 55 - 0
tracim/views/core_api/user_controller.py Ver arquivo

1
+from pyramid.config import Configurator
2
+from sqlalchemy.orm.exc import NoResultFound
3
+
4
+from tracim.lib.utils.authorization import require_same_user_or_profile
5
+from tracim.models import Group
6
+from tracim.models.context_models import WorkspaceInContext
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
+    UserNotExist
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 UserIdPathSchema, \
20
+    WorkspaceDigestSchema
21
+
22
+
23
+class UserController(Controller):
24
+
25
+    @hapic.with_api_doc()
26
+    @hapic.handle_exception(NotAuthentificated, HTTPStatus.UNAUTHORIZED)
27
+    @hapic.handle_exception(InsufficientUserProfile, HTTPStatus.FORBIDDEN)
28
+    @hapic.handle_exception(UserNotExist, HTTPStatus.NOT_FOUND)
29
+    @require_same_user_or_profile(Group.TIM_ADMIN)
30
+    @hapic.input_path(UserIdPathSchema())
31
+    @hapic.output_body(WorkspaceDigestSchema(many=True),)
32
+    def user_workspace(self, context, request: TracimRequest, hapic_data=None):
33
+        """
34
+        Get list of user workspaces
35
+        """
36
+        app_config = request.registry.settings['CFG']
37
+        wapi = WorkspaceApi(
38
+            current_user=request.current_user,  # User
39
+            session=request.dbsession,
40
+            config=app_config,
41
+        )
42
+        return [
43
+            WorkspaceInContext(workspace, request.dbsession, app_config)
44
+            for workspace in wapi.get_all_for_user(request.candidate_user)
45
+        ]
46
+
47
+    def bind(self, configurator: Configurator) -> None:
48
+        """
49
+        Create all routes and views using pyramid configurator
50
+        for this controller
51
+        """
52
+
53
+        # Applications
54
+        configurator.add_route('user_workspace', '/users/{user_id}/workspaces', request_method='GET')  # nopep8
55
+        configurator.add_view(self.user_workspace, route_name='user_workspace')

+ 86 - 0
tracim/views/core_api/workspace_controller.py Ver arquivo

1
+import typing
2
+
3
+from pyramid.config import Configurator
4
+from sqlalchemy.orm.exc import NoResultFound
5
+
6
+from tracim.lib.core.userworkspace import RoleApi
7
+from tracim.lib.utils.authorization import require_workspace_role
8
+from tracim.models.context_models import WorkspaceInContext, \
9
+    UserRoleWorkspaceInContext
10
+from tracim.models.data import UserRoleInWorkspace
11
+
12
+try:  # Python 3.5+
13
+    from http import HTTPStatus
14
+except ImportError:
15
+    from http import client as HTTPStatus
16
+
17
+from tracim import hapic, TracimRequest
18
+from tracim.exceptions import NotAuthentificated, InsufficientUserProfile, \
19
+    WorkspaceNotFound
20
+from tracim.lib.core.user import UserApi
21
+from tracim.lib.core.workspace import WorkspaceApi
22
+from tracim.views.controllers import Controller
23
+from tracim.views.core_api.schemas import WorkspaceSchema, UserSchema, \
24
+    WorkspaceIdPathSchema, WorkspaceMemberSchema
25
+
26
+
27
+class WorkspaceController(Controller):
28
+
29
+    @hapic.with_api_doc()
30
+    @hapic.handle_exception(NotAuthentificated, HTTPStatus.UNAUTHORIZED)
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())
35
+    @hapic.output_body(WorkspaceSchema())
36
+    def workspace(self, context, request: TracimRequest, hapic_data=None):
37
+        """
38
+        Get workspace informations
39
+        """
40
+        wid = hapic_data.path['workspace_id']
41
+        app_config = request.registry.settings['CFG']
42
+        wapi = WorkspaceApi(
43
+            current_user=request.current_user,  # User
44
+            session=request.dbsession,
45
+            config=app_config,
46
+        )
47
+        return wapi.get_workspace_with_context(request.current_workspace)
48
+
49
+    @hapic.with_api_doc()
50
+    @hapic.handle_exception(NotAuthentificated, HTTPStatus.UNAUTHORIZED)
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())
55
+    @hapic.output_body(WorkspaceMemberSchema(many=True))
56
+    def workspaces_members(
57
+            self,
58
+            context,
59
+            request: TracimRequest,
60
+            hapic_data=None
61
+    ) -> typing.List[UserRoleWorkspaceInContext]:
62
+        """
63
+        Get Members of this workspace
64
+        """
65
+        app_config = request.registry.settings['CFG']
66
+        rapi = RoleApi(
67
+            current_user=request.current_user,
68
+            session=request.dbsession,
69
+            config=app_config,
70
+        )
71
+        return [
72
+            rapi.get_user_role_workspace_with_context(user_role)
73
+            for user_role in rapi.get_all_for_workspace(request.current_workspace)
74
+        ]
75
+
76
+    def bind(self, configurator: Configurator) -> None:
77
+        """
78
+        Create all routes and views using pyramid configurator
79
+        for this controller
80
+        """
81
+
82
+        # Applications
83
+        configurator.add_route('workspace', '/workspaces/{workspace_id}', request_method='GET')  # nopep8
84
+        configurator.add_view(self.workspace, route_name='workspace')
85
+        configurator.add_route('workspace_members', '/workspaces/{workspace_id}/members', request_method='GET')  # nopep8
86
+        configurator.add_view(self.workspaces_members, route_name='workspace_members')  # nopep8