Browse Source

Big refactoring of App + Experimental support for color.json

Guénaël Muller 6 years ago
parent
commit
abfcc27c83
46 changed files with 560 additions and 417 deletions
  1. 1 0
      .gitignore
  2. 4 0
      backend/README.md
  3. 7 0
      backend/development.ini.sample
  4. 71 0
      backend/tracim_backend/app_models/applications.py
  5. 37 73
      backend/tracim_backend/app_models/contents.py
  6. 11 0
      backend/tracim_backend/app_models/validator.py
  7. 33 0
      backend/tracim_backend/app_models/workspace_menu_entries.py
  8. 148 4
      backend/tracim_backend/config.py
  9. 4 0
      backend/tracim_backend/exceptions.py
  10. 11 0
      backend/tracim_backend/extensions.py
  11. 1 1
      backend/tracim_backend/fixtures/content.py
  12. 70 0
      backend/tracim_backend/lib/core/application.py
  13. 3 3
      backend/tracim_backend/lib/core/content.py
  14. 1 1
      backend/tracim_backend/lib/mail_notifier/notifier.py
  15. 1 1
      backend/tracim_backend/lib/utils/authentification.py
  16. 5 7
      backend/tracim_backend/lib/utils/authorization.py
  17. 1 1
      backend/tracim_backend/lib/utils/request.py
  18. 4 5
      backend/tracim_backend/lib/utils/utils.py
  19. 1 1
      backend/tracim_backend/lib/webdav/dav_provider.py
  20. 1 1
      backend/tracim_backend/lib/webdav/design.py
  21. 1 1
      backend/tracim_backend/lib/webdav/resources.py
  22. 1 1
      backend/tracim_backend/lib/webdav/utils.py
  23. 1 1
      backend/tracim_backend/models/__init__.py
  24. 0 117
      backend/tracim_backend/models/applications.py
  25. 8 4
      backend/tracim_backend/models/context_models.py
  26. 3 3
      backend/tracim_backend/models/data.py
  27. 0 71
      backend/tracim_backend/models/workspace_menu_entries.py
  28. 1 1
      backend/tracim_backend/tests/__init__.py
  29. 1 1
      backend/tracim_backend/tests/functional/test_contents.py
  30. 1 1
      backend/tracim_backend/tests/functional/test_mail_notification.py
  31. 10 2
      backend/tracim_backend/tests/functional/test_system.py
  32. 26 39
      backend/tracim_backend/tests/functional/test_user.py
  33. 46 42
      backend/tracim_backend/tests/functional/test_workspaces.py
  34. 1 1
      backend/tracim_backend/tests/library/test_content_api.py
  35. 1 1
      backend/tracim_backend/tests/models/test_content.py
  36. 1 1
      backend/tracim_backend/tests/models/test_content_revision.py
  37. 2 2
      backend/tracim_backend/views/contents_api/comment_controller.py
  38. 3 3
      backend/tracim_backend/views/contents_api/file_controller.py
  39. 3 3
      backend/tracim_backend/views/contents_api/html_document_controller.py
  40. 3 3
      backend/tracim_backend/views/contents_api/threads_controller.py
  41. 10 9
      backend/tracim_backend/views/core_api/schemas.py
  42. 1 1
      backend/tracim_backend/views/core_api/session_controller.py
  43. 9 5
      backend/tracim_backend/views/core_api/system_controller.py
  44. 2 2
      backend/tracim_backend/views/core_api/user_controller.py
  45. 2 2
      backend/tracim_backend/views/core_api/workspace_controller.py
  46. 8 2
      backend/tracim_backend/views/frontend.py

+ 1 - 0
.gitignore View File

6
 frontend_lib/dist/tracim_frontend_lib.js
6
 frontend_lib/dist/tracim_frontend_lib.js
7
 npm-debug.log
7
 npm-debug.log
8
 package-lock.json
8
 package-lock.json
9
+color.json

+ 4 - 0
backend/README.md View File

81
 
81
 
82
     cp wsgidav.conf.sample wsgidav.conf
82
     cp wsgidav.conf.sample wsgidav.conf
83
 
83
 
84
+if not did before, you need to create a color.json file at root of tracim_v2 :
85
+   
86
+    cp ../color.json.sample ../color.json
87
+
84
 ## Run Tracim_backend ##
88
 ## Run Tracim_backend ##
85
 
89
 
86
 ### With Uwsgi ###
90
 ### With Uwsgi ###

+ 7 - 0
backend/development.ini.sample View File

193
 # organisation.
193
 # organisation.
194
 # frontend.dist_folder_path = /home/user/tracim_v2/frontend/dist
194
 # frontend.dist_folder_path = /home/user/tracim_v2/frontend/dist
195
 
195
 
196
+### Color
197
+# check for color.json file in tracim_v2, check by default in tracim_v2 parent
198
+# dir of backend.
199
+# you can set a specific file path here
200
+# color.config_file_path = /home/user/tracim_v2/color.json
201
+
202
+
196
 ###
203
 ###
197
 # wsgi server configuration
204
 # wsgi server configuration
198
 ###
205
 ###

+ 71 - 0
backend/tracim_backend/app_models/applications.py View File

1
+# coding=utf-8
2
+import typing
3
+
4
+from tracim_backend.app_models.contents import ContentType
5
+
6
+
7
+class Application(object):
8
+    """
9
+    Application class with data needed for frontend
10
+    """
11
+    def __init__(
12
+            self,
13
+            label: str,
14
+            slug: str,
15
+            fa_icon: str,
16
+            is_active: bool,
17
+            config: typing.Dict[str, str],
18
+            main_route: str,
19
+            app_config: 'CFG',
20
+    ) -> None:
21
+        """
22
+        @param label: public label of application
23
+        @param slug: identifier of application
24
+        @param fa_icon: font awesome icon class
25
+        @param is_active: True if application enable, False if inactive
26
+        @param config: a dict with eventual application config
27
+        @param main_route: the route of the frontend "home" screen of
28
+        the application. For exemple, if you have an application
29
+        called "calendar", the main route will be something
30
+        like /#/workspace/{wid}/calendar.
31
+        """
32
+        self.label = label
33
+        self.slug = slug
34
+        self.fa_icon = fa_icon
35
+        self.hexcolor = self._get_hexcolor_or_default(slug, app_config)
36
+        self.is_active = is_active
37
+        self.config = config
38
+        self.main_route = main_route
39
+        self.content_types = []
40
+
41
+    # TODO - G.M - 2018-08-07 - Refactor slug coherence issue like this one.
42
+    # we probably should not have 2 kind of slug
43
+    @property
44
+    def minislug(self):
45
+        return self.slug.replace('contents/', '')
46
+
47
+    def add_content_type(
48
+            self,
49
+            label: str,
50
+            slug: str,
51
+            creation_label: str,
52
+            available_statuses: typing.List['ContentStatus'],
53
+            slug_alias: typing.List[str] = None,
54
+    ):
55
+        content_type = ContentType(
56
+            slug=slug,
57
+            fa_icon=self.fa_icon,
58
+            label=label,
59
+            hexcolor=self.hexcolor,
60
+            creation_label=creation_label,
61
+            available_statuses=available_statuses,
62
+            slug_alias=slug_alias,
63
+        )
64
+        self.content_types.append(content_type)
65
+
66
+    def _get_hexcolor_or_default(self, slug: str, app_config: 'CFG') -> str:
67
+        assert app_config.APPS_COLORS
68
+        assert 'primary' in app_config.APPS_COLORS
69
+        if slug in app_config.APPS_COLORS:
70
+            return app_config.APPS_COLORS[slug]
71
+        return app_config.APPS_COLORS['primary']

backend/tracim_backend/models/contents.py → backend/tracim_backend/app_models/contents.py View File

2
 import typing
2
 import typing
3
 from enum import Enum
3
 from enum import Enum
4
 
4
 
5
+from tracim_backend.extensions import APP_LIST
5
 from tracim_backend.exceptions import ContentTypeNotExist
6
 from tracim_backend.exceptions import ContentTypeNotExist
6
 from tracim_backend.exceptions import ContentStatusNotExist
7
 from tracim_backend.exceptions import ContentStatusNotExist
7
-from tracim_backend.models.applications import html_documents
8
-from tracim_backend.models.applications import _file
9
-from tracim_backend.models.applications import folder
10
-from tracim_backend.models.applications import thread
11
-from tracim_backend.models.applications import markdownpluspage
12
-
13
 
8
 
14
 ####
9
 ####
15
 # Content Status
10
 # Content Status
11
+from tracim_backend.lib.core.application import ApplicationApi
16
 
12
 
17
 
13
 
18
 class GlobalStatus(Enum):
14
 class GlobalStatus(Enum):
132
         self.slug_alias = slug_alias
128
         self.slug_alias = slug_alias
133
 
129
 
134
 
130
 
135
-thread_type = ContentType(
136
-    slug='thread',
137
-    fa_icon=thread.fa_icon,
138
-    hexcolor=thread.hexcolor,
139
-    label='Thread',
140
-    creation_label='Discuss about a topic',
141
-    available_statuses=CONTENT_STATUS.get_all(),
142
-)
143
-
144
-file_type = ContentType(
145
-    slug='file',
146
-    fa_icon=_file.fa_icon,
147
-    hexcolor=_file.hexcolor,
148
-    label='File',
149
-    creation_label='Upload a file',
150
-    available_statuses=CONTENT_STATUS.get_all(),
151
-)
152
-
153
-markdownpluspage_type = ContentType(
154
-    slug='markdownpage',
155
-    fa_icon=markdownpluspage.fa_icon,
156
-    hexcolor=markdownpluspage.hexcolor,
157
-    label='Rich Markdown File',
158
-    creation_label='Create a Markdown document',
159
-    available_statuses=CONTENT_STATUS.get_all(),
160
-)
161
-
162
-html_documents_type = ContentType(
163
-    slug='html-document',
164
-    fa_icon=html_documents.fa_icon,
165
-    hexcolor=html_documents.hexcolor,
166
-    label='Text Document',
167
-    creation_label='Write a document',
168
-    available_statuses=CONTENT_STATUS.get_all(),
169
-    slug_alias=['page']
170
-)
171
-
172
-# TODO - G.M - 31-05-2018 - Set Better folder params
173
-folder_type = ContentType(
174
-    slug='folder',
175
-    fa_icon=folder.fa_icon,
176
-    hexcolor=folder.hexcolor,
177
-    label='Folder',
178
-    creation_label='Create a folder',
179
-    available_statuses=CONTENT_STATUS.get_all(),
180
-)
181
-
131
+thread_type = 'thread'
132
+file_type = 'file'
133
+markdownpluspage_type = 'markdownpage'
134
+html_documents_type = 'html-document'
135
+folder_type = 'folder'
182
 
136
 
183
 # TODO - G.M - 31-05-2018 - Set Better Event params
137
 # TODO - G.M - 31-05-2018 - Set Better Event params
184
 event_type = ContentType(
138
 event_type = ContentType(
185
     slug='event',
139
     slug='event',
186
-    fa_icon=thread.fa_icon,
187
-    hexcolor=thread.hexcolor,
140
+    fa_icon='',
141
+    hexcolor='',
188
     label='Event',
142
     label='Event',
189
     creation_label='Event',
143
     creation_label='Event',
190
     available_statuses=CONTENT_STATUS.get_all(),
144
     available_statuses=CONTENT_STATUS.get_all(),
193
 # TODO - G.M - 31-05-2018 - Set Better Event params
147
 # TODO - G.M - 31-05-2018 - Set Better Event params
194
 comment_type = ContentType(
148
 comment_type = ContentType(
195
     slug='comment',
149
     slug='comment',
196
-    fa_icon=thread.fa_icon,
197
-    hexcolor=thread.hexcolor,
150
+    fa_icon='',
151
+    hexcolor='',
198
     label='Comment',
152
     label='Comment',
199
     creation_label='Comment',
153
     creation_label='Comment',
200
     available_statuses=CONTENT_STATUS.get_all(),
154
     available_statuses=CONTENT_STATUS.get_all(),
206
     ContentType List
160
     ContentType List
207
     """
161
     """
208
     Any_SLUG = 'any'
162
     Any_SLUG = 'any'
209
-    Folder = folder_type
210
     Comment = comment_type
163
     Comment = comment_type
211
     Event = event_type
164
     Event = event_type
212
-    File = file_type
213
-    Page = html_documents_type
214
-    Thread = thread_type
215
 
165
 
216
-    def __init__(self, extend_content_status: typing.List[ContentType]):
217
-        self._content_types = [self.Folder]
218
-        self._content_types.extend(extend_content_status)
166
+    @property
167
+    def Folder(self):
168
+        return self.get_one_by_slug('folder')
169
+
170
+    @property
171
+    def File(self):
172
+        return self.get_one_by_slug('file')
173
+
174
+    @property
175
+    def Page(self):
176
+        return self.get_one_by_slug('html-document')
177
+
178
+    @property
179
+    def Thread(self):
180
+        return self.get_one_by_slug('thread')
181
+
182
+    def __init__(self, app_list: typing.List['Application']):
183
+        self.app_list = app_list
219
         self._special_contents_types = [self.Comment]
184
         self._special_contents_types = [self.Comment]
220
         self._extra_slugs = [self.Any_SLUG]
185
         self._extra_slugs = [self.Any_SLUG]
221
 
186
 
187
+    @property
188
+    def _content_types(self):
189
+        app_api = ApplicationApi(self.app_list)
190
+        content_types = app_api.get_content_types()
191
+        content_types.extend(self._special_contents_types)
192
+        return content_types
193
+
222
     def get_one_by_slug(self, slug: str) -> ContentType:
194
     def get_one_by_slug(self, slug: str) -> ContentType:
223
         """
195
         """
224
         Get ContentType object according to slug
196
         Get ContentType object according to slug
258
         return allowed_types_slug
230
         return allowed_types_slug
259
 
231
 
260
 
232
 
261
-CONTENT_TYPES = ContentTypeList(
262
-    [
263
-        thread_type,
264
-        file_type,
265
-        # TODO - G.M - 2018-08-02 - Restore markdown page content
266
-        #    markdownpluspage_type,
267
-        html_documents_type,
268
-    ]
269
-)
233
+CONTENT_TYPES = ContentTypeList(APP_LIST)

+ 11 - 0
backend/tracim_backend/app_models/validator.py View File

1
+from marshmallow.validate import OneOf
2
+from tracim_backend.app_models.contents import CONTENT_TYPES
3
+
4
+# TODO - G.M - 2018-08-08 - [GlobalVar] Refactor Global var
5
+# of tracim_backend, Be careful ALL_CONTENT_TYPES_VALIDATOR is a global_var !
6
+
7
+ALL_CONTENT_TYPES_VALIDATOR = OneOf(choices=[])
8
+
9
+
10
+def update_validators():
11
+    ALL_CONTENT_TYPES_VALIDATOR.choices = CONTENT_TYPES.endpoint_allowed_types_slug()  # nopep8

+ 33 - 0
backend/tracim_backend/app_models/workspace_menu_entries.py View File

1
+class WorkspaceMenuEntry(object):
2
+    """
3
+    Application class with data needed for frontend
4
+    """
5
+    def __init__(
6
+            self,
7
+            label: str,
8
+            slug: str,
9
+            fa_icon: str,
10
+            hexcolor: str,
11
+            route: str,
12
+    ) -> None:
13
+        self.slug = slug
14
+        self.label = label
15
+        self.route = route
16
+        self.hexcolor = hexcolor
17
+        self.fa_icon = fa_icon
18
+
19
+
20
+dashboard_menu_entry = WorkspaceMenuEntry(
21
+  slug='dashboard',
22
+  label='Dashboard',
23
+  route='/#/workspaces/{workspace_id}/dashboard',
24
+  hexcolor='#252525',
25
+  fa_icon="signal",
26
+)
27
+all_content_menu_entry = WorkspaceMenuEntry(
28
+  slug="contents/all",
29
+  label="All Contents",
30
+  route="/#/workspaces/{workspace_id}/contents",
31
+  hexcolor="#fdfdfd",
32
+  fa_icon="th",
33
+)

+ 148 - 4
backend/tracim_backend/config.py View File

1
 # -*- coding: utf-8 -*-
1
 # -*- coding: utf-8 -*-
2
+import json
2
 from urllib.parse import urlparse
3
 from urllib.parse import urlparse
3
 
4
 
4
 import os
5
 import os
5
 from paste.deploy.converters import asbool
6
 from paste.deploy.converters import asbool
7
+from tracim_backend.app_models.validator import update_validators
8
+from tracim_backend.extensions import APP_LIST
6
 from tracim_backend.lib.utils.logger import logger
9
 from tracim_backend.lib.utils.logger import logger
7
 from depot.manager import DepotManager
10
 from depot.manager import DepotManager
8
-from tracim_backend.models.contents import CONTENT_TYPES
11
+from tracim_backend.app_models.applications import Application
12
+from tracim_backend.app_models.contents import CONTENT_TYPES
13
+from tracim_backend.app_models.contents import CONTENT_STATUS
9
 from tracim_backend.models.data import ActionDescription
14
 from tracim_backend.models.data import ActionDescription
10
 
15
 
11
 
16
 
12
-
13
 class CFG(object):
17
 class CFG(object):
14
     """Object used for easy access to config file parameters."""
18
     """Object used for easy access to config file parameters."""
15
 
19
 
41
         ###
45
         ###
42
         # General
46
         # General
43
         ###
47
         ###
48
+        backend_folder = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))  # nopep8
49
+        tracim_v2_folder = os.path.dirname(backend_folder)
50
+        default_color_config_file_path = os.path.join(tracim_v2_folder, 'color.json')  # nopep8
51
+        self.COLOR_CONFIG_FILE_PATH = settings.get(
52
+            'color.config_file_path', default_color_config_file_path
53
+        )
54
+        if not os.path.exists(self.COLOR_CONFIG_FILE_PATH):
55
+            raise Exception(
56
+                'ERROR: {} file does not exist. '
57
+                'please create it or set color.config_file_path'
58
+                'with a correct value'.format(self.COLOR_CONFIG_FILE_PATH)
59
+            )
60
+
61
+        try:
62
+            with open(self.COLOR_CONFIG_FILE_PATH) as json_file:
63
+                self.APPS_COLORS = json.load(json_file)
64
+        except Exception as e:
65
+            raise Exception(
66
+                'Error: {} file could not be load as json'.format(self.COLOR_CONFIG_FILE_PATH) # nopep8
67
+            ) from e
44
 
68
 
69
+        try:
70
+            self.APPS_COLORS['primary']
71
+        except KeyError as e:
72
+            raise Exception(
73
+                'Error: primary color is required in {} file'.format(
74
+                    self.COLOR_CONFIG_FILE_PATH)  # nopep8
75
+            ) from e
76
+
77
+        self._set_default_app()
45
         mandatory_msg = \
78
         mandatory_msg = \
46
             'ERROR: {} configuration is mandatory. Set it before continuing.'
79
             'ERROR: {} configuration is mandatory. Set it before continuing.'
47
         self.DEPOT_STORAGE_DIR = settings.get(
80
         self.DEPOT_STORAGE_DIR = settings.get(
450
         # INFO - G.M - 2018-08-06 - we pretend that frontend_dist_folder
483
         # INFO - G.M - 2018-08-06 - we pretend that frontend_dist_folder
451
         # is probably in frontend subfolder
484
         # is probably in frontend subfolder
452
         # of tracim_v2 parent of both backend and frontend
485
         # of tracim_v2 parent of both backend and frontend
453
-        backend_folder = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))  # nopep8
454
-        tracim_v2_folder = os.path.dirname(backend_folder)
455
         frontend_dist_folder = os.path.join(tracim_v2_folder, 'frontend', 'dist')  # nopep8
486
         frontend_dist_folder = os.path.join(tracim_v2_folder, 'frontend', 'dist')  # nopep8
456
 
487
 
457
         self.FRONTEND_DIST_FOLDER_PATH = settings.get(
488
         self.FRONTEND_DIST_FOLDER_PATH = settings.get(
467
             )
498
             )
468
 
499
 
469
     def configure_filedepot(self):
500
     def configure_filedepot(self):
501
+
502
+        # TODO - G.M - 2018-08-08 - [GlobalVar] Refactor Global var
503
+        # of tracim_backend, Be careful DepotManager is a Singleton !
504
+
470
         depot_storage_name = self.DEPOT_STORAGE_NAME
505
         depot_storage_name = self.DEPOT_STORAGE_NAME
471
         depot_storage_path = self.DEPOT_STORAGE_DIR
506
         depot_storage_path = self.DEPOT_STORAGE_DIR
472
         depot_storage_settings = {'depot.storage_path': depot_storage_path}
507
         depot_storage_settings = {'depot.storage_path': depot_storage_path}
475
             depot_storage_settings,
510
             depot_storage_settings,
476
         )
511
         )
477
 
512
 
513
+    def _set_default_app(self):
514
+        calendar = Application(
515
+            label='Calendar',
516
+            slug='calendar',
517
+            fa_icon='calendar',
518
+            is_active=False,
519
+            config={},
520
+            main_route='/#/workspaces/{workspace_id}/calendar',
521
+            app_config=self
522
+        )
523
+
524
+        thread = Application(
525
+            label='Threads',
526
+            slug='contents/thread',
527
+            fa_icon='comments-o',
528
+            is_active=True,
529
+            config={},
530
+            main_route='/#/workspaces/{workspace_id}/contents?type=thread',
531
+            app_config=self
532
+        )
533
+        thread.add_content_type(
534
+            slug='thread',
535
+            label='Thread',
536
+            creation_label='Discuss about a topic',
537
+            available_statuses=CONTENT_STATUS.get_all(),
538
+        )
539
+
540
+        folder = Application(
541
+            label='Folder',
542
+            slug='contents/folder',
543
+            fa_icon='folder-open-o',
544
+            is_active=True,
545
+            config={},
546
+            main_route='',
547
+            app_config=self
548
+        )
549
+        folder.add_content_type(
550
+            slug='folder',
551
+            label='Folder',
552
+            creation_label='Create a folder',
553
+            available_statuses=CONTENT_STATUS.get_all(),
554
+        )
555
+
556
+        _file = Application(
557
+            label='Files',
558
+            slug='contents/file',
559
+            fa_icon='paperclip',
560
+            is_active=True,
561
+            config={},
562
+            main_route='/#/workspaces/{workspace_id}/contents?type=file',
563
+            app_config=self,
564
+        )
565
+        _file.add_content_type(
566
+            slug='file',
567
+            label='File',
568
+            creation_label='Upload a file',
569
+            available_statuses=CONTENT_STATUS.get_all(),
570
+        )
571
+
572
+        markdownpluspage = Application(
573
+            label='Markdown Plus Documents',
574
+            # TODO - G.M - 24-05-2018 - Check label
575
+            slug='content/markdownpluspage',
576
+            fa_icon='file-code-o',
577
+            is_active=False,
578
+            config={},
579
+            main_route='/#/workspaces/{workspace_id}/contents?type=markdownpluspage',
580
+            # nopep8
581
+            app_config=self,
582
+        )
583
+        markdownpluspage.add_content_type(
584
+            slug='markdownpage',
585
+            label='Rich Markdown File',
586
+            creation_label='Create a Markdown document',
587
+            available_statuses=CONTENT_STATUS.get_all(),
588
+        )
589
+
590
+        html_documents = Application(
591
+            label='Text Documents',  # TODO - G.M - 24-05-2018 - Check label
592
+            slug='contents/html-document',
593
+            fa_icon='file-text-o',
594
+            is_active=True,
595
+            config={},
596
+            main_route='/#/workspaces/{workspace_id}/contents?type=html-document',
597
+            app_config=self
598
+        )
599
+        html_documents.add_content_type(
600
+            slug='html-document',
601
+            label='Text Document',
602
+            creation_label='Write a document',
603
+            available_statuses=CONTENT_STATUS.get_all(),
604
+            slug_alias=['page']
605
+        )
606
+
607
+        # TODO - G.M - 2018-08-08 - [GlobalVar] Refactor Global var
608
+        # of tracim_backend, Be careful APP_LIST is a global_var
609
+        APP_LIST.clear()
610
+        APP_LIST.extend([
611
+            html_documents,
612
+            markdownpluspage,
613
+            _file,
614
+            thread,
615
+            folder,
616
+            calendar,
617
+        ])
618
+        # TODO - G.M - 2018-08-08 - We need to update validators each time
619
+        # APP_LIST is updated.
620
+        update_validators()
621
+
478
     class CST(object):
622
     class CST(object):
479
         ASYNC = 'ASYNC'
623
         ASYNC = 'ASYNC'
480
         SYNC = 'SYNC'
624
         SYNC = 'SYNC'

+ 4 - 0
backend/tracim_backend/exceptions.py View File

211
 
211
 
212
 class PageNotFound(TracimException):
212
 class PageNotFound(TracimException):
213
     pass
213
     pass
214
+
215
+
216
+class AppDoesNotExist(TracimException):
217
+    pass

+ 11 - 0
backend/tracim_backend/extensions.py View File

1
 from hapic import Hapic
1
 from hapic import Hapic
2
 
2
 
3
 hapic = Hapic()
3
 hapic = Hapic()
4
+
5
+# TODO - G.M - 2018-08-08 - [GlobalVar] Refactor Global var of tracim_backend
6
+
7
+# INFO - G.M - 2018-08-08 - APP_LIST
8
+# APP_LIST is one of the few "global_val" in tracim_backend, with hapic
9
+# and ALL_CONTENT_TYPES_VALIDATOR.
10
+# The goal of this is to be able to get current list of loaded app.
11
+# List is empty until config load apps.
12
+# If you need to update APP_LIST, think about updating Content validator like
13
+# ALL_CONTENT_TYPES_VALIDATOR , see  update_validators() method.
14
+APP_LIST = []

+ 1 - 1
backend/tracim_backend/fixtures/content.py View File

8
 from tracim_backend.lib.core.content import ContentApi
8
 from tracim_backend.lib.core.content import ContentApi
9
 from tracim_backend.lib.core.userworkspace import RoleApi
9
 from tracim_backend.lib.core.userworkspace import RoleApi
10
 from tracim_backend.lib.core.workspace import WorkspaceApi
10
 from tracim_backend.lib.core.workspace import WorkspaceApi
11
-from tracim_backend.models.contents import CONTENT_TYPES
11
+from tracim_backend.app_models.contents import CONTENT_TYPES
12
 from tracim_backend.models.data import UserRoleInWorkspace
12
 from tracim_backend.models.data import UserRoleInWorkspace
13
 from tracim_backend.models.revision_protection import new_revision
13
 from tracim_backend.models.revision_protection import new_revision
14
 
14
 

+ 70 - 0
backend/tracim_backend/lib/core/application.py View File

1
+import typing
2
+from copy import copy
3
+
4
+from tracim_backend.exceptions import AppDoesNotExist
5
+from tracim_backend.app_models.workspace_menu_entries import WorkspaceMenuEntry
6
+from tracim_backend.app_models.workspace_menu_entries import dashboard_menu_entry
7
+from tracim_backend.app_models.workspace_menu_entries import all_content_menu_entry
8
+
9
+
10
+class ApplicationApi(object):
11
+
12
+    def __init__(
13
+        self,
14
+        app_list,
15
+        show_all: bool = False,
16
+    ) ->  None:
17
+        self.apps = app_list
18
+        self.show_all = show_all
19
+
20
+    def get_one(self, slug):
21
+        for app in self.apps:
22
+            if app.slug == slug:
23
+                return app
24
+        raise AppDoesNotExist('Application {app} does not exist'.format(app=slug))  # nopep8
25
+
26
+    def get_all(self):
27
+        active_apps = []
28
+        for app in self.apps:
29
+            if self.show_all or app.is_active:
30
+                active_apps.append(app)
31
+
32
+        return active_apps
33
+
34
+    def get_content_types(self):
35
+        active_content_types = []
36
+        for app in self.get_all():
37
+            if app.content_types:
38
+                for content_type in app.content_types:
39
+                    active_content_types.append(content_type)
40
+        return active_content_types
41
+
42
+    def get_default_workspace_menu_entry(
43
+            self,
44
+            workspace: 'Workspace',
45
+    ) -> typing.List[WorkspaceMenuEntry]:
46
+        """
47
+        Get default menu entry for a workspace
48
+        """
49
+        menu_entries = [
50
+            copy(dashboard_menu_entry),
51
+            copy(all_content_menu_entry),
52
+        ]
53
+        for app in self.get_all():
54
+            if app.main_route:
55
+                new_entry = WorkspaceMenuEntry(
56
+                    slug=app.slug,
57
+                    label=app.label,
58
+                    hexcolor=app.hexcolor,
59
+                    fa_icon=app.fa_icon,
60
+                    route=app.main_route
61
+                )
62
+                menu_entries.append(new_entry)
63
+
64
+        for entry in menu_entries:
65
+            entry.route = entry.route.replace(
66
+                '{workspace_id}',
67
+                str(workspace.workspace_id)
68
+            )
69
+
70
+        return menu_entries

+ 3 - 3
backend/tracim_backend/lib/core/content.py View File

34
 from tracim_backend.exceptions import ContentNotFound
34
 from tracim_backend.exceptions import ContentNotFound
35
 from tracim_backend.exceptions import WorkspacesDoNotMatch
35
 from tracim_backend.exceptions import WorkspacesDoNotMatch
36
 from tracim_backend.lib.utils.utils import current_date_for_filename
36
 from tracim_backend.lib.utils.utils import current_date_for_filename
37
-from tracim_backend.models.contents import CONTENT_STATUS
38
-from tracim_backend.models.contents import ContentType
39
-from tracim_backend.models.contents import CONTENT_TYPES
37
+from tracim_backend.app_models.contents import CONTENT_STATUS
38
+from tracim_backend.app_models.contents import ContentType
39
+from tracim_backend.app_models.contents import CONTENT_TYPES
40
 from tracim_backend.models.revision_protection import new_revision
40
 from tracim_backend.models.revision_protection import new_revision
41
 from tracim_backend.models.auth import User
41
 from tracim_backend.models.auth import User
42
 from tracim_backend.models.data import ActionDescription
42
 from tracim_backend.models.data import ActionDescription

+ 1 - 1
backend/tracim_backend/lib/mail_notifier/notifier.py View File

20
 from tracim_backend.lib.utils.utils import get_login_frontend_url
20
 from tracim_backend.lib.utils.utils import get_login_frontend_url
21
 from tracim_backend.lib.utils.utils import get_email_logo_frontend_url
21
 from tracim_backend.lib.utils.utils import get_email_logo_frontend_url
22
 from tracim_backend.models.auth import User
22
 from tracim_backend.models.auth import User
23
-from tracim_backend.models.contents import CONTENT_TYPES
23
+from tracim_backend.app_models.contents import CONTENT_TYPES
24
 from tracim_backend.models.context_models import ContentInContext
24
 from tracim_backend.models.context_models import ContentInContext
25
 from tracim_backend.models.context_models import WorkspaceInContext
25
 from tracim_backend.models.context_models import WorkspaceInContext
26
 from tracim_backend.models.data import ActionDescription
26
 from tracim_backend.models.data import ActionDescription

+ 1 - 1
backend/tracim_backend/lib/utils/authentification.py View File

3
 from pyramid.request import Request
3
 from pyramid.request import Request
4
 from sqlalchemy.orm.exc import NoResultFound
4
 from sqlalchemy.orm.exc import NoResultFound
5
 
5
 
6
-from tracim_backend import TracimRequest
6
+from tracim_backend.lib.utils.request import TracimRequest
7
 from tracim_backend.exceptions import UserDoesNotExist
7
 from tracim_backend.exceptions import UserDoesNotExist
8
 from tracim_backend.lib.core.user import UserApi
8
 from tracim_backend.lib.core.user import UserApi
9
 from tracim_backend.models import User
9
 from tracim_backend.models import User

+ 5 - 7
backend/tracim_backend/lib/utils/authorization.py View File

5
 from pyramid.interfaces import IAuthorizationPolicy
5
 from pyramid.interfaces import IAuthorizationPolicy
6
 from zope.interface import implementer
6
 from zope.interface import implementer
7
 
7
 
8
-from tracim_backend.models.contents import ContentType
9
-from tracim_backend.models.contents import CONTENT_TYPES
8
+from tracim_backend.app_models.contents import ContentType
9
+from tracim_backend.app_models.contents import CONTENT_TYPES
10
 
10
 
11
 try:
11
 try:
12
     from json.decoder import JSONDecodeError
12
     from json.decoder import JSONDecodeError
13
 except ImportError:  # python3.4
13
 except ImportError:  # python3.4
14
     JSONDecodeError = ValueError
14
     JSONDecodeError = ValueError
15
 
15
 
16
-from tracim_backend.models.contents import ContentType
17
 from tracim_backend.exceptions import InsufficientUserRoleInWorkspace
16
 from tracim_backend.exceptions import InsufficientUserRoleInWorkspace
18
 from tracim_backend.exceptions import ContentTypeNotAllowed
17
 from tracim_backend.exceptions import ContentTypeNotAllowed
19
 from tracim_backend.exceptions import InsufficientUserProfile
18
 from tracim_backend.exceptions import InsufficientUserProfile
133
     return decorator
132
     return decorator
134
 
133
 
135
 
134
 
136
-def require_content_types(content_types: typing.List['ContentType']) -> typing.Callable:  # nopep8
135
+def require_content_types(content_types_slug: typing.List[str]) -> typing.Callable:  # nopep8
137
     """
136
     """
138
     Restricts access to specific file type or raise an exception.
137
     Restricts access to specific file type or raise an exception.
139
     Check role for candidate_workspace.
138
     Check role for candidate_workspace.
140
-    :param content_types: list of ContentType object
139
+    :param content_types_slug: list of slug of content_types
141
     :return: decorator
140
     :return: decorator
142
     """
141
     """
143
     def decorator(func: typing.Callable) -> typing.Callable:
142
     def decorator(func: typing.Callable) -> typing.Callable:
144
         @functools.wraps(func)
143
         @functools.wraps(func)
145
         def wrapper(self, context, request: 'TracimRequest') -> typing.Callable:
144
         def wrapper(self, context, request: 'TracimRequest') -> typing.Callable:
146
             content = request.current_content
145
             content = request.current_content
147
-            current_content_type_slug = CONTENT_TYPES.get_one_by_slug(content.type).slug
148
-            content_types_slug = [content_type.slug for content_type in content_types]  # nopep8
146
+            current_content_type_slug = CONTENT_TYPES.get_one_by_slug(content.type).slug  # nopep8
149
             if current_content_type_slug in content_types_slug:
147
             if current_content_type_slug in content_types_slug:
150
                 return func(self, context, request)
148
                 return func(self, context, request)
151
             raise ContentTypeNotAllowed()
149
             raise ContentTypeNotAllowed()

+ 1 - 1
backend/tracim_backend/lib/utils/request.py View File

15
 from tracim_backend.exceptions import UserDoesNotExist
15
 from tracim_backend.exceptions import UserDoesNotExist
16
 from tracim_backend.exceptions import WorkspaceNotFound
16
 from tracim_backend.exceptions import WorkspaceNotFound
17
 from tracim_backend.exceptions import ImmutableAttribute
17
 from tracim_backend.exceptions import ImmutableAttribute
18
-from tracim_backend.models.contents import CONTENT_TYPES
18
+from tracim_backend.app_models.contents import CONTENT_TYPES
19
 from tracim_backend.lib.core.content import ContentApi
19
 from tracim_backend.lib.core.content import ContentApi
20
 from tracim_backend.lib.core.user import UserApi
20
 from tracim_backend.lib.core.user import UserApi
21
 from tracim_backend.lib.core.workspace import WorkspaceApi
21
 from tracim_backend.lib.core.workspace import WorkspaceApi

+ 4 - 5
backend/tracim_backend/lib/utils/utils.py View File

7
 from redis import Redis
7
 from redis import Redis
8
 from rq import Queue
8
 from rq import Queue
9
 
9
 
10
-from tracim_backend.config import CFG
11
 
10
 
12
 DATETIME_FORMAT = '%Y-%m-%dT%H:%M:%SZ'
11
 DATETIME_FORMAT = '%Y-%m-%dT%H:%M:%SZ'
13
 DEFAULT_WEBDAV_CONFIG_FILE = "wsgidav.conf"
12
 DEFAULT_WEBDAV_CONFIG_FILE = "wsgidav.conf"
16
 WORKSPACE_FRONTEND_URL_SCHEMA = 'workspaces/{workspace_id}'  # nopep8
15
 WORKSPACE_FRONTEND_URL_SCHEMA = 'workspaces/{workspace_id}'  # nopep8
17
 
16
 
18
 
17
 
19
-def get_root_frontend_url(config: CFG) -> str:
18
+def get_root_frontend_url(config: 'CFG') -> str:
20
     """
19
     """
21
     Return website base url with always '/' at the end
20
     Return website base url with always '/' at the end
22
     """
21
     """
28
     return base_url
27
     return base_url
29
 
28
 
30
 
29
 
31
-def get_login_frontend_url(config: CFG):
30
+def get_login_frontend_url(config: 'CFG'):
32
     """
31
     """
33
     Return login page url
32
     Return login page url
34
     """
33
     """
35
     return get_root_frontend_url(config) + 'login'
34
     return get_root_frontend_url(config) + 'login'
36
 
35
 
37
 
36
 
38
-def get_email_logo_frontend_url(config: CFG):
37
+def get_email_logo_frontend_url(config: 'CFG'):
39
     # TODO - G.M - 11-06-2018 - [emailTemplateURL] correct value for email_logo_frontend_url  # nopep8
38
     # TODO - G.M - 11-06-2018 - [emailTemplateURL] correct value for email_logo_frontend_url  # nopep8
40
     return 'data:image/png;base64,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'  # nopep8'
39
     return 'data:image/png;base64,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'  # nopep8'
41
 
40
 
42
 
41
 
43
-def get_redis_connection(config: CFG) -> Redis:
42
+def get_redis_connection(config: 'CFG') -> Redis:
44
     """
43
     """
45
     :param config: current app_config
44
     :param config: current app_config
46
     :return: redis connection
45
     :return: redis connection

+ 1 - 1
backend/tracim_backend/lib/webdav/dav_provider.py View File

8
 from tracim_backend import CFG
8
 from tracim_backend import CFG
9
 from tracim_backend.lib.webdav.utils import transform_to_bdd, HistoryType, \
9
 from tracim_backend.lib.webdav.utils import transform_to_bdd, HistoryType, \
10
     SpecialFolderExtension
10
     SpecialFolderExtension
11
-from tracim_backend.models.contents import CONTENT_TYPES
11
+from tracim_backend.app_models.contents import CONTENT_TYPES
12
 
12
 
13
 from wsgidav.dav_provider import DAVProvider
13
 from wsgidav.dav_provider import DAVProvider
14
 from wsgidav.lock_manager import LockManager
14
 from wsgidav.lock_manager import LockManager

+ 1 - 1
backend/tracim_backend/lib/webdav/design.py View File

1
 #coding: utf8
1
 #coding: utf8
2
 from datetime import datetime
2
 from datetime import datetime
3
 
3
 
4
-from tracim_backend.models.contents import CONTENT_TYPES
4
+from tracim_backend.app_models.contents import CONTENT_TYPES
5
 from tracim_backend.models.data import VirtualEvent
5
 from tracim_backend.models.data import VirtualEvent
6
 from tracim_backend.models import data
6
 from tracim_backend.models import data
7
 
7
 

+ 1 - 1
backend/tracim_backend/lib/webdav/resources.py View File

19
     FakeFileStream
19
     FakeFileStream
20
 from tracim_backend.lib.webdav.utils import transform_to_bdd
20
 from tracim_backend.lib.webdav.utils import transform_to_bdd
21
 from tracim_backend.lib.core.workspace import WorkspaceApi
21
 from tracim_backend.lib.core.workspace import WorkspaceApi
22
-from tracim_backend.models.contents import CONTENT_TYPES
22
+from tracim_backend.app_models.contents import CONTENT_TYPES
23
 from tracim_backend.models.data import User, ContentRevisionRO
23
 from tracim_backend.models.data import User, ContentRevisionRO
24
 from tracim_backend.models.data import Workspace
24
 from tracim_backend.models.data import Workspace
25
 from tracim_backend.models.data import Content
25
 from tracim_backend.models.data import Content

+ 1 - 1
backend/tracim_backend/lib/webdav/utils.py View File

4
 from os.path import normpath as base_normpath
4
 from os.path import normpath as base_normpath
5
 
5
 
6
 from sqlalchemy.orm import Session
6
 from sqlalchemy.orm import Session
7
-from tracim_backend.models.contents import CONTENT_TYPES
7
+from tracim_backend.app_models.contents import CONTENT_TYPES
8
 from wsgidav import util
8
 from wsgidav import util
9
 from wsgidav import compat
9
 from wsgidav import compat
10
 
10
 

+ 1 - 1
backend/tracim_backend/models/__init__.py View File

5
 from sqlalchemy.orm import configure_mappers
5
 from sqlalchemy.orm import configure_mappers
6
 import zope.sqlalchemy
6
 import zope.sqlalchemy
7
 from .meta import DeclarativeBase
7
 from .meta import DeclarativeBase
8
-from .revision_protection import prevent_content_revision_delete
8
+from tracim_backend.models.revision_protection import prevent_content_revision_delete
9
 # import or define all models here to ensure they are attached to the
9
 # import or define all models here to ensure they are attached to the
10
 # Base.metadata prior to any initialization routines
10
 # Base.metadata prior to any initialization routines
11
 from tracim_backend.models.auth import User, Group, Permission
11
 from tracim_backend.models.auth import User, Group, Permission

+ 0 - 117
backend/tracim_backend/models/applications.py View File

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
-            fa_icon: str,
14
-            hexcolor: str,
15
-            is_active: bool,
16
-            config: typing.Dict[str, str],
17
-            main_route: str,
18
-    ) -> None:
19
-        """
20
-        @param label: public label of application
21
-        @param slug: identifier of application
22
-        @param icon: font awesome icon class
23
-        @param hexcolor: hexa color of application main color
24
-        @param is_active: True if application enable, False if inactive
25
-        @param config: a dict with eventual application config
26
-        @param main_route: the route of the frontend "home" screen of
27
-        the application. For exemple, if you have an application
28
-        called "calendar", the main route will be something
29
-        like /#/workspace/{wid}/calendar.
30
-        """
31
-        self.label = label
32
-        self.slug = slug
33
-        self.fa_icon = fa_icon
34
-        self.hexcolor = hexcolor
35
-        self.is_active = is_active
36
-        self.config = config
37
-        self.main_route = main_route
38
-
39
-    # TODO - G.M - 2018-08-07 - Refactor slug coherence issue like this one.
40
-    # we probably should not have 2 kind of slug
41
-    @property
42
-    def minislug(self):
43
-        return self.slug.replace('contents/', '')
44
-
45
-
46
-# default apps
47
-calendar = Application(
48
-    label='Calendar',
49
-    slug='calendar',
50
-    fa_icon='calendar',
51
-    hexcolor='#757575',
52
-    is_active=True,
53
-    config={},
54
-    main_route='/#/workspaces/{workspace_id}/calendar',
55
-)
56
-
57
-thread = Application(
58
-    label='Threads',
59
-    slug='contents/thread',
60
-    fa_icon='comments-o',
61
-    hexcolor='#ad4cf9',
62
-    is_active=True,
63
-    config={},
64
-    main_route='/#/workspaces/{workspace_id}/contents?type=thread',
65
-
66
-)
67
-
68
-folder = Application(
69
-    label='Folder',
70
-    slug='contents/folder',
71
-    fa_icon='folder-open-o',
72
-    hexcolor='#252525',
73
-    is_active=True,
74
-    config={},
75
-    main_route='',
76
-)
77
-
78
-_file = Application(
79
-    label='Files',
80
-    slug='contents/file',
81
-    fa_icon='paperclip',
82
-    hexcolor='#FF9900',
83
-    is_active=True,
84
-    config={},
85
-    main_route='/#/workspaces/{workspace_id}/contents?type=file',
86
-)
87
-
88
-markdownpluspage = Application(
89
-    label='Markdown Plus Documents',  # TODO - G.M - 24-05-2018 - Check label
90
-    slug='contents/markdownpluspage',
91
-    fa_icon='file-code-o',
92
-    hexcolor='#f12d2d',
93
-    is_active=True,
94
-    config={},
95
-    main_route='/#/workspaces/{workspace_id}/contents?type=markdownpluspage',
96
-)
97
-
98
-html_documents = Application(
99
-    label='Text Documents',  # TODO - G.M - 24-05-2018 - Check label
100
-    slug='contents/html-document',
101
-    fa_icon='file-text-o',
102
-    hexcolor='#3f52e3',
103
-    is_active=True,
104
-    config={},
105
-    main_route='/#/workspaces/{workspace_id}/contents?type=html-document',
106
-)
107
-# TODO - G.M - 08-06-2018 - This is hardcoded lists of app, make this dynamic.
108
-# List of applications
109
-applications = [
110
-    html_documents,
111
-    # TODO - G.M - 2018-08-02 - Restore markdownpage app
112
-    # markdownpluspage,
113
-    _file,
114
-    thread,
115
-    folder,
116
-    # calendar,
117
-]

+ 8 - 4
backend/tracim_backend/models/context_models.py View File

7
 from sqlalchemy.orm import Session
7
 from sqlalchemy.orm import Session
8
 from tracim_backend.config import CFG
8
 from tracim_backend.config import CFG
9
 from tracim_backend.config import PreviewDim
9
 from tracim_backend.config import PreviewDim
10
+from tracim_backend.extensions import APP_LIST
11
+from tracim_backend.lib.core.application import ApplicationApi
10
 from tracim_backend.lib.utils.utils import get_root_frontend_url
12
 from tracim_backend.lib.utils.utils import get_root_frontend_url
11
 from tracim_backend.lib.utils.utils import CONTENT_FRONTEND_URL_SCHEMA
13
 from tracim_backend.lib.utils.utils import CONTENT_FRONTEND_URL_SCHEMA
12
 from tracim_backend.lib.utils.utils import WORKSPACE_FRONTEND_URL_SCHEMA
14
 from tracim_backend.lib.utils.utils import WORKSPACE_FRONTEND_URL_SCHEMA
17
 from tracim_backend.models.data import Workspace
19
 from tracim_backend.models.data import Workspace
18
 from tracim_backend.models.data import UserRoleInWorkspace
20
 from tracim_backend.models.data import UserRoleInWorkspace
19
 from tracim_backend.models.roles import WorkspaceRoles
21
 from tracim_backend.models.roles import WorkspaceRoles
20
-from tracim_backend.models.workspace_menu_entries import default_workspace_menu_entry  # nopep8
21
-from tracim_backend.models.workspace_menu_entries import WorkspaceMenuEntry
22
-from tracim_backend.models.contents import CONTENT_TYPES
22
+from tracim_backend.app_models.workspace_menu_entries import WorkspaceMenuEntry
23
+from tracim_backend.app_models.contents import CONTENT_TYPES
23
 
24
 
24
 
25
 
25
 class PreviewAllowedDim(object):
26
 class PreviewAllowedDim(object):
463
         # order to not use hardcoded list
464
         # order to not use hardcoded list
464
         # list should be able to change (depending on activated/disabled
465
         # list should be able to change (depending on activated/disabled
465
         # apps)
466
         # apps)
466
-        return default_workspace_menu_entry(self.workspace)
467
+        app_api = ApplicationApi(
468
+            APP_LIST
469
+        )
470
+        return app_api.get_default_workspace_menu_entry(self.workspace)
467
 
471
 
468
     @property
472
     @property
469
     def frontend_url(self):
473
     def frontend_url(self):

+ 3 - 3
backend/tracim_backend/models/data.py View File

291
                 ]
291
                 ]
292
 
292
 
293
 
293
 
294
-from tracim_backend.models.contents import CONTENT_STATUS
295
-from tracim_backend.models.contents import ContentStatus
296
-from tracim_backend.models.contents import CONTENT_TYPES
294
+from tracim_backend.app_models.contents import CONTENT_STATUS
295
+from tracim_backend.app_models.contents import ContentStatus
296
+from tracim_backend.app_models.contents import CONTENT_TYPES
297
 # TODO - G.M - 30-05-2018 - Drop this old code when whe are sure nothing
297
 # TODO - G.M - 30-05-2018 - Drop this old code when whe are sure nothing
298
 # is lost .
298
 # is lost .
299
 
299
 

+ 0 - 71
backend/tracim_backend/models/workspace_menu_entries.py View File

1
-# coding=utf-8
2
-import typing
3
-from copy import copy
4
-
5
-from tracim_backend.models.applications import applications
6
-from tracim_backend.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
-            fa_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.fa_icon = fa_icon
26
-
27
-dashboard_menu_entry = WorkspaceMenuEntry(
28
-  slug='dashboard',
29
-  label='Dashboard',
30
-  route='/#/workspaces/{workspace_id}/dashboard',
31
-  hexcolor='#252525',
32
-  fa_icon="signal",
33
-)
34
-all_content_menu_entry = WorkspaceMenuEntry(
35
-  slug="contents/all",
36
-  label="All Contents",
37
-  route="/#/workspaces/{workspace_id}/contents",
38
-  hexcolor="#fdfdfd",
39
-  fa_icon="th",
40
-)
41
-
42
-# TODO - G.M - 08-06-2018 - This is hardcoded default menu entry,
43
-#  of app, make this dynamic (and loaded from application system)
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
-                fa_icon=app.fa_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

+ 1 - 1
backend/tracim_backend/tests/__init__.py View File

14
 from tracim_backend.models import DeclarativeBase
14
 from tracim_backend.models import DeclarativeBase
15
 from tracim_backend.models import get_session_factory
15
 from tracim_backend.models import get_session_factory
16
 from tracim_backend.models import get_tm_session
16
 from tracim_backend.models import get_tm_session
17
-from tracim_backend.models.contents import CONTENT_TYPES
17
+from tracim_backend.app_models.contents import CONTENT_TYPES
18
 from tracim_backend.models.data import Workspace
18
 from tracim_backend.models.data import Workspace
19
 from tracim_backend.models.data import ContentRevisionRO
19
 from tracim_backend.models.data import ContentRevisionRO
20
 from tracim_backend.models.data import Content
20
 from tracim_backend.models.data import Content

+ 1 - 1
backend/tracim_backend/tests/functional/test_contents.py View File

5
 from tracim_backend.lib.core.content import ContentApi
5
 from tracim_backend.lib.core.content import ContentApi
6
 from tracim_backend.lib.core.workspace import WorkspaceApi
6
 from tracim_backend.lib.core.workspace import WorkspaceApi
7
 from tracim_backend.models import get_tm_session
7
 from tracim_backend.models import get_tm_session
8
-from tracim_backend.models.contents import CONTENT_TYPES
8
+from tracim_backend.app_models.contents import CONTENT_TYPES
9
 from tracim_backend.models.revision_protection import new_revision
9
 from tracim_backend.models.revision_protection import new_revision
10
 import io
10
 import io
11
 
11
 

+ 1 - 1
backend/tracim_backend/tests/functional/test_mail_notification.py View File

11
 from tracim_backend.fixtures.content import Content as ContentFixture
11
 from tracim_backend.fixtures.content import Content as ContentFixture
12
 from tracim_backend.lib.utils.utils import get_redis_connection
12
 from tracim_backend.lib.utils.utils import get_redis_connection
13
 from tracim_backend.lib.utils.utils import get_rq_queue
13
 from tracim_backend.lib.utils.utils import get_rq_queue
14
-from tracim_backend.models.contents import CONTENT_TYPES
14
+from tracim_backend.app_models.contents import CONTENT_TYPES
15
 
15
 
16
 from tracim_backend.lib.core.content import ContentApi
16
 from tracim_backend.lib.core.content import ContentApi
17
 from tracim_backend.lib.core.user import UserApi
17
 from tracim_backend.lib.core.user import UserApi

+ 10 - 2
backend/tracim_backend/tests/functional/test_system.py View File

1
 # coding=utf-8
1
 # coding=utf-8
2
-from tracim_backend.models.contents import CONTENT_TYPES
2
+import transaction
3
+from tracim_backend.extensions import APP_LIST
4
+from tracim_backend.lib.core.application import ApplicationApi
5
+from tracim_backend.models import get_tm_session
6
+from tracim_backend.app_models.contents import CONTENT_TYPES
3
 from tracim_backend.tests import FunctionalTest
7
 from tracim_backend.tests import FunctionalTest
4
-from tracim_backend.models.applications import applications
5
 
8
 
6
 """
9
 """
7
 Tests for /api/v2/system subpath endpoints.
10
 Tests for /api/v2/system subpath endpoints.
26
         )
29
         )
27
         res = self.testapp.get('/api/v2/system/applications', status=200)
30
         res = self.testapp.get('/api/v2/system/applications', status=200)
28
         res = res.json_body
31
         res = res.json_body
32
+        dbsession = get_tm_session(self.session_factory, transaction.manager)
33
+        app_api = ApplicationApi(
34
+            app_list=APP_LIST,
35
+        )
36
+        applications = app_api.get_all()
29
         assert len(res) == len(applications)
37
         assert len(res) == len(applications)
30
         for counter, application in enumerate(applications):
38
         for counter, application in enumerate(applications):
31
             assert res[counter]['label'] == application.label
39
             assert res[counter]['label'] == application.label

+ 26 - 39
backend/tracim_backend/tests/functional/test_user.py View File

7
 import transaction
7
 import transaction
8
 
8
 
9
 from tracim_backend import models
9
 from tracim_backend import models
10
+from tracim_backend.extensions import APP_LIST
11
+from tracim_backend.lib.core.application import ApplicationApi
10
 from tracim_backend.lib.core.content import ContentApi
12
 from tracim_backend.lib.core.content import ContentApi
11
 from tracim_backend.lib.core.user import UserApi
13
 from tracim_backend.lib.core.user import UserApi
12
 from tracim_backend.lib.core.group import GroupApi
14
 from tracim_backend.lib.core.group import GroupApi
13
 from tracim_backend.lib.core.userworkspace import RoleApi
15
 from tracim_backend.lib.core.userworkspace import RoleApi
14
 from tracim_backend.lib.core.workspace import WorkspaceApi
16
 from tracim_backend.lib.core.workspace import WorkspaceApi
15
 from tracim_backend.models import get_tm_session
17
 from tracim_backend.models import get_tm_session
16
-from tracim_backend.models.contents import CONTENT_TYPES
18
+from tracim_backend.app_models.contents import CONTENT_TYPES
17
 from tracim_backend.models.data import UserRoleInWorkspace
19
 from tracim_backend.models.data import UserRoleInWorkspace
18
 from tracim_backend.models.revision_protection import new_revision
20
 from tracim_backend.models.revision_protection import new_revision
19
 from tracim_backend.tests import FunctionalTest
21
 from tracim_backend.tests import FunctionalTest
2369
         """
2371
         """
2370
         Check obtain all workspaces reachables for user with user auth.
2372
         Check obtain all workspaces reachables for user with user auth.
2371
         """
2373
         """
2374
+        dbsession = get_tm_session(self.session_factory, transaction.manager)
2375
+        admin = dbsession.query(models.User) \
2376
+            .filter(models.User.email == 'admin@admin.admin') \
2377
+            .one()
2378
+
2379
+        workspace_api = WorkspaceApi(
2380
+            session=dbsession,
2381
+            current_user=admin,
2382
+            config=self.app_config,
2383
+        )
2384
+        workspace = workspace_api.get_one(1)
2385
+        app_api = ApplicationApi(
2386
+            APP_LIST
2387
+        )
2388
+
2389
+        default_sidebar_entry = app_api.get_default_workspace_menu_entry(workspace=workspace)  # nope8
2372
         self.testapp.authorization = (
2390
         self.testapp.authorization = (
2373
             'Basic',
2391
             'Basic',
2374
             (
2392
             (
2382
         assert workspace['workspace_id'] == 1
2400
         assert workspace['workspace_id'] == 1
2383
         assert workspace['label'] == 'Business'
2401
         assert workspace['label'] == 'Business'
2384
         assert workspace['slug'] == 'business'
2402
         assert workspace['slug'] == 'business'
2385
-        assert len(workspace['sidebar_entries']) == 5
2386
-
2387
-        # TODO - G.M - 2018-08-02 - Better test for sidebar entry, make it
2388
-        # not fixed on active application/content-file
2389
-        sidebar_entry = workspace['sidebar_entries'][0]
2390
-        assert sidebar_entry['slug'] == 'dashboard'
2391
-        assert sidebar_entry['label'] == 'Dashboard'
2392
-        assert sidebar_entry['route'] == '/#/workspaces/1/dashboard'  # nopep8
2393
-        assert sidebar_entry['hexcolor'] == "#252525"
2394
-        assert sidebar_entry['fa_icon'] == "signal"
2395
-
2396
-        sidebar_entry = workspace['sidebar_entries'][1]
2397
-        assert sidebar_entry['slug'] == 'contents/all'
2398
-        assert sidebar_entry['label'] == 'All Contents'
2399
-        assert sidebar_entry['route'] == "/#/workspaces/1/contents"  # nopep8
2400
-        assert sidebar_entry['hexcolor'] == "#fdfdfd"
2401
-        assert sidebar_entry['fa_icon'] == "th"
2402
-
2403
-        sidebar_entry = workspace['sidebar_entries'][2]
2404
-        assert sidebar_entry['slug'] == 'contents/html-document'
2405
-        assert sidebar_entry['label'] == 'Text Documents'
2406
-        assert sidebar_entry['route'] == '/#/workspaces/1/contents?type=html-document'  # nopep8
2407
-        assert sidebar_entry['hexcolor'] == "#3f52e3"
2408
-        assert sidebar_entry['fa_icon'] == "file-text-o"
2409
-
2410
-        sidebar_entry = workspace['sidebar_entries'][3]
2411
-        assert sidebar_entry['slug'] == 'contents/file'
2412
-        assert sidebar_entry['label'] == 'Files'
2413
-        assert sidebar_entry['route'] == "/#/workspaces/1/contents?type=file"  # nopep8
2414
-        assert sidebar_entry['hexcolor'] == "#FF9900"
2415
-        assert sidebar_entry['fa_icon'] == "paperclip"
2416
-
2417
-        sidebar_entry = workspace['sidebar_entries'][4]
2418
-        assert sidebar_entry['slug'] == 'contents/thread'
2419
-        assert sidebar_entry['label'] == 'Threads'
2420
-        assert sidebar_entry['route'] == "/#/workspaces/1/contents?type=thread"  # nopep8
2421
-        assert sidebar_entry['hexcolor'] == "#ad4cf9"
2422
-        assert sidebar_entry['fa_icon'] == "comments-o"
2403
+        assert len(workspace['sidebar_entries']) == len(default_sidebar_entry)
2404
+        for counter, sidebar_entry in enumerate(default_sidebar_entry):
2405
+            workspace['sidebar_entries'][counter]['slug'] = sidebar_entry.slug
2406
+            workspace['sidebar_entries'][counter]['label'] = sidebar_entry.label
2407
+            workspace['sidebar_entries'][counter]['route'] = sidebar_entry.route
2408
+            workspace['sidebar_entries'][counter]['hexcolor'] = sidebar_entry.hexcolor  # nopep8
2409
+            workspace['sidebar_entries'][counter]['fa_icon'] = sidebar_entry.fa_icon  # nopep8
2423
 
2410
 
2424
 
2411
 
2425
     def test_api__get_user_workspaces__err_403__unallowed_user(self):
2412
     def test_api__get_user_workspaces__err_403__unallowed_user(self):

+ 46 - 42
backend/tracim_backend/tests/functional/test_workspaces.py View File

7
 from depot.io.utils import FileIntent
7
 from depot.io.utils import FileIntent
8
 
8
 
9
 from tracim_backend import models
9
 from tracim_backend import models
10
+from tracim_backend.extensions import APP_LIST
11
+from tracim_backend.lib.core.application import ApplicationApi
10
 from tracim_backend.lib.core.content import ContentApi
12
 from tracim_backend.lib.core.content import ContentApi
11
 from tracim_backend.lib.core.workspace import WorkspaceApi
13
 from tracim_backend.lib.core.workspace import WorkspaceApi
12
 from tracim_backend.models import get_tm_session
14
 from tracim_backend.models import get_tm_session
13
-from tracim_backend.models.contents import CONTENT_TYPES
15
+from tracim_backend.app_models.contents import CONTENT_TYPES
14
 from tracim_backend.tests import FunctionalTest
16
 from tracim_backend.tests import FunctionalTest
15
 from tracim_backend.tests import set_html_document_slug_to_legacy
17
 from tracim_backend.tests import set_html_document_slug_to_legacy
16
 from tracim_backend.fixtures.content import Content as ContentFixtures
18
 from tracim_backend.fixtures.content import Content as ContentFixtures
28
         """
30
         """
29
         Check obtain workspace reachable for user.
31
         Check obtain workspace reachable for user.
30
         """
32
         """
33
+        dbsession = get_tm_session(self.session_factory, transaction.manager)
34
+        admin = dbsession.query(models.User) \
35
+            .filter(models.User.email == 'admin@admin.admin') \
36
+            .one()
37
+
38
+        workspace_api = WorkspaceApi(
39
+            session=dbsession,
40
+            current_user=admin,
41
+            config=self.app_config,
42
+        )
43
+        workspace = workspace_api.get_one(1)
44
+        app_api = ApplicationApi(
45
+            APP_LIST
46
+        )
47
+        default_sidebar_entry = app_api.get_default_workspace_menu_entry(workspace=workspace)  # nope8
48
+
31
         self.testapp.authorization = (
49
         self.testapp.authorization = (
32
             'Basic',
50
             'Basic',
33
             (
51
             (
41
         assert workspace['slug'] == 'business'
59
         assert workspace['slug'] == 'business'
42
         assert workspace['label'] == 'Business'
60
         assert workspace['label'] == 'Business'
43
         assert workspace['description'] == 'All importants documents'
61
         assert workspace['description'] == 'All importants documents'
44
-        assert len(workspace['sidebar_entries']) == 5
45
-
46
-        # TODO - G.M - 2018-08-02 - Better test for sidebar entry, make it
47
-        # not fixed on active application/content-file
48
-        sidebar_entry = workspace['sidebar_entries'][0]
49
-        assert sidebar_entry['slug'] == 'dashboard'
50
-        assert sidebar_entry['label'] == 'Dashboard'
51
-        assert sidebar_entry['route'] == '/#/workspaces/1/dashboard'  # nopep8
52
-        assert sidebar_entry['hexcolor'] == "#252525"
53
-        assert sidebar_entry['fa_icon'] == "signal"
54
-
55
-        sidebar_entry = workspace['sidebar_entries'][1]
56
-        assert sidebar_entry['slug'] == 'contents/all'
57
-        assert sidebar_entry['label'] == 'All Contents'
58
-        assert sidebar_entry['route'] == "/#/workspaces/1/contents"  # nopep8
59
-        assert sidebar_entry['hexcolor'] == "#fdfdfd"
60
-        assert sidebar_entry['fa_icon'] == "th"
61
-
62
-        sidebar_entry = workspace['sidebar_entries'][2]
63
-        assert sidebar_entry['slug'] == 'contents/html-document'
64
-        assert sidebar_entry['label'] == 'Text Documents'
65
-        assert sidebar_entry['route'] == '/#/workspaces/1/contents?type=html-document'  # nopep8
66
-        assert sidebar_entry['hexcolor'] == "#3f52e3"
67
-        assert sidebar_entry['fa_icon'] == "file-text-o"
68
-
69
-        sidebar_entry = workspace['sidebar_entries'][3]
70
-        assert sidebar_entry['slug'] == 'contents/file'
71
-        assert sidebar_entry['label'] == 'Files'
72
-        assert sidebar_entry['route'] == "/#/workspaces/1/contents?type=file"  # nopep8
73
-        assert sidebar_entry['hexcolor'] == "#FF9900"
74
-        assert sidebar_entry['fa_icon'] == "paperclip"
75
-
76
-        sidebar_entry = workspace['sidebar_entries'][4]
77
-        assert sidebar_entry['slug'] == 'contents/thread'
78
-        assert sidebar_entry['label'] == 'Threads'
79
-        assert sidebar_entry['route'] == "/#/workspaces/1/contents?type=thread"  # nopep8
80
-        assert sidebar_entry['hexcolor'] == "#ad4cf9"
81
-        assert sidebar_entry['fa_icon'] == "comments-o"
62
+
63
+        assert len(workspace['sidebar_entries']) == len(default_sidebar_entry)
64
+        for counter, sidebar_entry in enumerate(default_sidebar_entry):
65
+            workspace['sidebar_entries'][counter]['slug'] = sidebar_entry.slug
66
+            workspace['sidebar_entries'][counter]['label'] = sidebar_entry.label
67
+            workspace['sidebar_entries'][counter]['route'] = sidebar_entry.route
68
+            workspace['sidebar_entries'][counter]['hexcolor'] = sidebar_entry.hexcolor  # nopep8
69
+            workspace['sidebar_entries'][counter]['fa_icon'] = sidebar_entry.fa_icon  # nopep8
82
 
70
 
83
     def test_api__update_workspace__ok_200__nominal_case(self) -> None:
71
     def test_api__update_workspace__ok_200__nominal_case(self) -> None:
84
         """
72
         """
85
         Test update workspace
73
         Test update workspace
86
         """
74
         """
75
+        dbsession = get_tm_session(self.session_factory, transaction.manager)
76
+        admin = dbsession.query(models.User) \
77
+            .filter(models.User.email == 'admin@admin.admin') \
78
+            .one()
79
+
80
+        workspace_api = WorkspaceApi(
81
+            session=dbsession,
82
+            current_user=admin,
83
+            config=self.app_config,
84
+        )
85
+        workspace = workspace_api.get_one(1)
86
+        app_api = ApplicationApi(
87
+            APP_LIST
88
+        )
89
+        default_sidebar_entry = app_api.get_default_workspace_menu_entry(workspace=workspace)  # nope8
90
+
87
         self.testapp.authorization = (
91
         self.testapp.authorization = (
88
             'Basic',
92
             'Basic',
89
             (
93
             (
106
         assert workspace['slug'] == 'business'
110
         assert workspace['slug'] == 'business'
107
         assert workspace['label'] == 'Business'
111
         assert workspace['label'] == 'Business'
108
         assert workspace['description'] == 'All importants documents'
112
         assert workspace['description'] == 'All importants documents'
109
-        assert len(workspace['sidebar_entries']) == 5
113
+        assert len(workspace['sidebar_entries']) == len(default_sidebar_entry)
110
 
114
 
111
         # modify workspace
115
         # modify workspace
112
         res = self.testapp.put_json(
116
         res = self.testapp.put_json(
120
         assert workspace['slug'] == 'superworkspace'
124
         assert workspace['slug'] == 'superworkspace'
121
         assert workspace['label'] == 'superworkspace'
125
         assert workspace['label'] == 'superworkspace'
122
         assert workspace['description'] == 'mysuperdescription'
126
         assert workspace['description'] == 'mysuperdescription'
123
-        assert len(workspace['sidebar_entries']) == 5
127
+        assert len(workspace['sidebar_entries']) == len(default_sidebar_entry)
124
 
128
 
125
         # after
129
         # after
126
         res = self.testapp.get(
130
         res = self.testapp.get(
133
         assert workspace['slug'] == 'superworkspace'
137
         assert workspace['slug'] == 'superworkspace'
134
         assert workspace['label'] == 'superworkspace'
138
         assert workspace['label'] == 'superworkspace'
135
         assert workspace['description'] == 'mysuperdescription'
139
         assert workspace['description'] == 'mysuperdescription'
136
-        assert len(workspace['sidebar_entries']) == 5
140
+        assert len(workspace['sidebar_entries']) == len(default_sidebar_entry)
137
 
141
 
138
     def test_api__update_workspace__err_400__empty_label(self) -> None:
142
     def test_api__update_workspace__err_400__empty_label(self) -> None:
139
         """
143
         """

+ 1 - 1
backend/tracim_backend/tests/library/test_content_api.py View File

14
 from tracim_backend.lib.core.workspace import RoleApi
14
 from tracim_backend.lib.core.workspace import RoleApi
15
 # TODO - G.M - 28-03-2018 - [WorkspaceApi] Re-enable WorkspaceApi
15
 # TODO - G.M - 28-03-2018 - [WorkspaceApi] Re-enable WorkspaceApi
16
 from tracim_backend.lib.core.workspace import WorkspaceApi
16
 from tracim_backend.lib.core.workspace import WorkspaceApi
17
-from tracim_backend.models.contents import CONTENT_TYPES
17
+from tracim_backend.app_models.contents import CONTENT_TYPES
18
 from tracim_backend.models.revision_protection import new_revision
18
 from tracim_backend.models.revision_protection import new_revision
19
 from tracim_backend.models.auth import User
19
 from tracim_backend.models.auth import User
20
 from tracim_backend.models.auth import Group
20
 from tracim_backend.models.auth import Group

+ 1 - 1
backend/tracim_backend/tests/models/test_content.py View File

15
 from tracim_backend.models import User
15
 from tracim_backend.models import User
16
 from tracim_backend.models.data import ActionDescription
16
 from tracim_backend.models.data import ActionDescription
17
 from tracim_backend.models.data import ContentRevisionRO
17
 from tracim_backend.models.data import ContentRevisionRO
18
-from tracim_backend.models.contents import CONTENT_TYPES
18
+from tracim_backend.app_models.contents import CONTENT_TYPES
19
 from tracim_backend.models.data import Workspace
19
 from tracim_backend.models.data import Workspace
20
 from tracim_backend.tests import StandardTest
20
 from tracim_backend.tests import StandardTest
21
 
21
 

+ 1 - 1
backend/tracim_backend/tests/models/test_content_revision.py View File

5
 
5
 
6
 from tracim_backend.models import ContentRevisionRO
6
 from tracim_backend.models import ContentRevisionRO
7
 from tracim_backend.models import User
7
 from tracim_backend.models import User
8
-from tracim_backend.models.contents import CONTENT_TYPES
8
+from tracim_backend.app_models.contents import CONTENT_TYPES
9
 from tracim_backend.tests import DefaultTest
9
 from tracim_backend.tests import DefaultTest
10
 from tracim_backend.tests import eq_
10
 from tracim_backend.tests import eq_
11
 
11
 

+ 2 - 2
backend/tracim_backend/views/contents_api/comment_controller.py View File

7
 except ImportError:
7
 except ImportError:
8
     from http import client as HTTPStatus
8
     from http import client as HTTPStatus
9
 
9
 
10
-from tracim_backend import TracimRequest
10
+from tracim_backend.lib.utils.request import TracimRequest
11
 from tracim_backend.extensions import hapic
11
 from tracim_backend.extensions import hapic
12
 from tracim_backend.lib.core.content import ContentApi
12
 from tracim_backend.lib.core.content import ContentApi
13
 from tracim_backend.lib.core.workspace import WorkspaceApi
13
 from tracim_backend.lib.core.workspace import WorkspaceApi
20
 from tracim_backend.views.core_api.schemas import WorkspaceAndContentIdPathSchema
20
 from tracim_backend.views.core_api.schemas import WorkspaceAndContentIdPathSchema
21
 from tracim_backend.views.core_api.schemas import NoContentSchema
21
 from tracim_backend.views.core_api.schemas import NoContentSchema
22
 from tracim_backend.exceptions import EmptyCommentContentNotAllowed
22
 from tracim_backend.exceptions import EmptyCommentContentNotAllowed
23
-from tracim_backend.models.contents import CONTENT_TYPES
23
+from tracim_backend.app_models.contents import CONTENT_TYPES
24
 from tracim_backend.models.revision_protection import new_revision
24
 from tracim_backend.models.revision_protection import new_revision
25
 from tracim_backend.models.data import UserRoleInWorkspace
25
 from tracim_backend.models.data import UserRoleInWorkspace
26
 
26
 

+ 3 - 3
backend/tracim_backend/views/contents_api/file_controller.py View File

12
 except ImportError:
12
 except ImportError:
13
     from http import client as HTTPStatus
13
     from http import client as HTTPStatus
14
 
14
 
15
-from tracim_backend import TracimRequest
15
+from tracim_backend.lib.utils.request import TracimRequest
16
 from tracim_backend.extensions import hapic
16
 from tracim_backend.extensions import hapic
17
 from tracim_backend.lib.core.content import ContentApi
17
 from tracim_backend.lib.core.content import ContentApi
18
 from tracim_backend.views.controllers import Controller
18
 from tracim_backend.views.controllers import Controller
32
 from tracim_backend.models.data import UserRoleInWorkspace
32
 from tracim_backend.models.data import UserRoleInWorkspace
33
 from tracim_backend.models.context_models import ContentInContext
33
 from tracim_backend.models.context_models import ContentInContext
34
 from tracim_backend.models.context_models import RevisionInContext
34
 from tracim_backend.models.context_models import RevisionInContext
35
-from tracim_backend.models.contents import CONTENT_TYPES
36
-from tracim_backend.models.contents import file_type
35
+from tracim_backend.app_models.contents import CONTENT_TYPES
36
+from tracim_backend.app_models.contents import file_type
37
 from tracim_backend.models.revision_protection import new_revision
37
 from tracim_backend.models.revision_protection import new_revision
38
 from tracim_backend.exceptions import EmptyLabelNotAllowed
38
 from tracim_backend.exceptions import EmptyLabelNotAllowed
39
 from tracim_backend.exceptions import PageOfPreviewNotFound
39
 from tracim_backend.exceptions import PageOfPreviewNotFound

+ 3 - 3
backend/tracim_backend/views/contents_api/html_document_controller.py View File

11
 except ImportError:
11
 except ImportError:
12
     from http import client as HTTPStatus
12
     from http import client as HTTPStatus
13
 
13
 
14
-from tracim_backend import TracimRequest
14
+from tracim_backend.lib.utils.request import TracimRequest
15
 from tracim_backend.extensions import hapic
15
 from tracim_backend.extensions import hapic
16
 from tracim_backend.lib.core.content import ContentApi
16
 from tracim_backend.lib.core.content import ContentApi
17
 from tracim_backend.views.controllers import Controller
17
 from tracim_backend.views.controllers import Controller
26
 from tracim_backend.exceptions import EmptyLabelNotAllowed
26
 from tracim_backend.exceptions import EmptyLabelNotAllowed
27
 from tracim_backend.models.context_models import ContentInContext
27
 from tracim_backend.models.context_models import ContentInContext
28
 from tracim_backend.models.context_models import RevisionInContext
28
 from tracim_backend.models.context_models import RevisionInContext
29
-from tracim_backend.models.contents import CONTENT_TYPES
30
-from tracim_backend.models.contents import html_documents_type
29
+from tracim_backend.app_models.contents import CONTENT_TYPES
30
+from tracim_backend.app_models.contents import html_documents_type
31
 from tracim_backend.models.revision_protection import new_revision
31
 from tracim_backend.models.revision_protection import new_revision
32
 
32
 
33
 SWAGGER_TAG__HTML_DOCUMENT_ENDPOINTS = 'HTML documents'
33
 SWAGGER_TAG__HTML_DOCUMENT_ENDPOINTS = 'HTML documents'

+ 3 - 3
backend/tracim_backend/views/contents_api/threads_controller.py View File

10
 except ImportError:
10
 except ImportError:
11
     from http import client as HTTPStatus
11
     from http import client as HTTPStatus
12
 
12
 
13
-from tracim_backend import TracimRequest
13
+from tracim_backend.lib.utils.request import TracimRequest
14
 from tracim_backend.extensions import hapic
14
 from tracim_backend.extensions import hapic
15
 from tracim_backend.lib.core.content import ContentApi
15
 from tracim_backend.lib.core.content import ContentApi
16
 from tracim_backend.views.controllers import Controller
16
 from tracim_backend.views.controllers import Controller
25
 from tracim_backend.exceptions import EmptyLabelNotAllowed
25
 from tracim_backend.exceptions import EmptyLabelNotAllowed
26
 from tracim_backend.models.context_models import ContentInContext
26
 from tracim_backend.models.context_models import ContentInContext
27
 from tracim_backend.models.context_models import RevisionInContext
27
 from tracim_backend.models.context_models import RevisionInContext
28
-from tracim_backend.models.contents import CONTENT_TYPES
29
-from tracim_backend.models.contents import thread_type
28
+from tracim_backend.app_models.contents import CONTENT_TYPES
29
+from tracim_backend.app_models.contents import thread_type
30
 from tracim_backend.models.revision_protection import new_revision
30
 from tracim_backend.models.revision_protection import new_revision
31
 
31
 
32
 SWAGGER_TAG__THREAD_ENDPOINTS = 'Threads'
32
 SWAGGER_TAG__THREAD_ENDPOINTS = 'Threads'

+ 10 - 9
backend/tracim_backend/views/core_api/schemas.py View File

7
 
7
 
8
 from tracim_backend.lib.utils.utils import DATETIME_FORMAT
8
 from tracim_backend.lib.utils.utils import DATETIME_FORMAT
9
 from tracim_backend.models.auth import Profile
9
 from tracim_backend.models.auth import Profile
10
-from tracim_backend.models.contents import GlobalStatus
11
-from tracim_backend.models.contents import CONTENT_STATUS
12
-from tracim_backend.models.contents import CONTENT_TYPES
13
-from tracim_backend.models.contents import open_status
10
+from tracim_backend.app_models.contents import GlobalStatus
11
+from tracim_backend.app_models.contents import CONTENT_STATUS
12
+from tracim_backend.app_models.contents import CONTENT_TYPES
13
+from tracim_backend.app_models.contents import open_status
14
 from tracim_backend.models.context_models import ActiveContentFilter
14
 from tracim_backend.models.context_models import ActiveContentFilter
15
 from tracim_backend.models.context_models import AutocompleteQuery
15
 from tracim_backend.models.context_models import AutocompleteQuery
16
 from tracim_backend.models.context_models import ContentIdsQuery
16
 from tracim_backend.models.context_models import ContentIdsQuery
39
 from tracim_backend.models.context_models import LoginCredentials
39
 from tracim_backend.models.context_models import LoginCredentials
40
 from tracim_backend.models.data import UserRoleInWorkspace
40
 from tracim_backend.models.data import UserRoleInWorkspace
41
 from tracim_backend.models.data import ActionDescription
41
 from tracim_backend.models.data import ActionDescription
42
+from tracim_backend.app_models.validator import ALL_CONTENT_TYPES_VALIDATOR
42
 
43
 
43
 
44
 
44
 class UserDigestSchema(marshmallow.Schema):
45
 class UserDigestSchema(marshmallow.Schema):
357
     content_type = marshmallow.fields.String(
358
     content_type = marshmallow.fields.String(
358
         example=CONTENT_TYPES.Any_SLUG,
359
         example=CONTENT_TYPES.Any_SLUG,
359
         default=CONTENT_TYPES.Any_SLUG,
360
         default=CONTENT_TYPES.Any_SLUG,
360
-        validate=OneOf(CONTENT_TYPES.endpoint_allowed_types_slug())
361
+        validate=ALL_CONTENT_TYPES_VALIDATOR
361
     )
362
     )
362
 
363
 
363
     @post_load
364
     @post_load
607
 class ContentTypeSchema(marshmallow.Schema):
608
 class ContentTypeSchema(marshmallow.Schema):
608
     slug = marshmallow.fields.String(
609
     slug = marshmallow.fields.String(
609
         example='pagehtml',
610
         example='pagehtml',
610
-        validate=OneOf(CONTENT_TYPES.endpoint_allowed_types_slug()),
611
+        validate=ALL_CONTENT_TYPES_VALIDATOR,
611
     )
612
     )
612
     fa_icon = marshmallow.fields.String(
613
     fa_icon = marshmallow.fields.String(
613
         example='fa-file-text-o',
614
         example='fa-file-text-o',
661
     )
662
     )
662
     content_type = marshmallow.fields.String(
663
     content_type = marshmallow.fields.String(
663
         example='html-document',
664
         example='html-document',
664
-        validate=OneOf(CONTENT_TYPES.endpoint_allowed_types_slug()),
665
+        validate=ALL_CONTENT_TYPES_VALIDATOR,
665
     )
666
     )
666
     parent_id = marshmallow.fields.Integer(
667
     parent_id = marshmallow.fields.Integer(
667
         example=35,
668
         example=35,
696
     label = marshmallow.fields.Str(example='Intervention Report 12')
697
     label = marshmallow.fields.Str(example='Intervention Report 12')
697
     content_type = marshmallow.fields.Str(
698
     content_type = marshmallow.fields.Str(
698
         example='html-document',
699
         example='html-document',
699
-        validate=OneOf(CONTENT_TYPES.endpoint_allowed_types_slug()),
700
+        validate=ALL_CONTENT_TYPES_VALIDATOR,
700
     )
701
     )
701
     sub_content_types = marshmallow.fields.List(
702
     sub_content_types = marshmallow.fields.List(
702
         marshmallow.fields.String(
703
         marshmallow.fields.String(
703
             example='html-content',
704
             example='html-content',
704
-            validate=OneOf(CONTENT_TYPES.endpoint_allowed_types_slug())
705
+            validate=ALL_CONTENT_TYPES_VALIDATOR
705
         ),
706
         ),
706
         description='list of content types allowed as sub contents. '
707
         description='list of content types allowed as sub contents. '
707
                     'This field is required for folder contents, '
708
                     'This field is required for folder contents, '

+ 1 - 1
backend/tracim_backend/views/core_api/session_controller.py View File

5
 except ImportError:
5
 except ImportError:
6
     from http import client as HTTPStatus
6
     from http import client as HTTPStatus
7
 
7
 
8
-from tracim_backend import TracimRequest
8
+from tracim_backend.lib.utils.request import TracimRequest
9
 from tracim_backend.extensions import hapic
9
 from tracim_backend.extensions import hapic
10
 from tracim_backend.lib.core.user import UserApi
10
 from tracim_backend.lib.core.user import UserApi
11
 from tracim_backend.views.controllers import Controller
11
 from tracim_backend.views.controllers import Controller

+ 9 - 5
backend/tracim_backend/views/core_api/system_controller.py View File

2
 from pyramid.config import Configurator
2
 from pyramid.config import Configurator
3
 from tracim_backend.exceptions import NotAuthenticated
3
 from tracim_backend.exceptions import NotAuthenticated
4
 from tracim_backend.exceptions import InsufficientUserProfile
4
 from tracim_backend.exceptions import InsufficientUserProfile
5
+from tracim_backend.lib.core.application import ApplicationApi
5
 from tracim_backend.lib.utils.authorization import require_profile
6
 from tracim_backend.lib.utils.authorization import require_profile
6
 from tracim_backend.models import Group
7
 from tracim_backend.models import Group
7
-from tracim_backend.models.applications import applications
8
-from tracim_backend.models.contents import CONTENT_TYPES
8
+from tracim_backend.app_models.contents import CONTENT_TYPES
9
 
9
 
10
 try:  # Python 3.5+
10
 try:  # Python 3.5+
11
     from http import HTTPStatus
11
     from http import HTTPStatus
12
 except ImportError:
12
 except ImportError:
13
     from http import client as HTTPStatus
13
     from http import client as HTTPStatus
14
 
14
 
15
-from tracim_backend import TracimRequest
16
-from tracim_backend.extensions import hapic
15
+from tracim_backend.lib.utils.request import TracimRequest
16
+from tracim_backend.extensions import hapic, APP_LIST
17
 from tracim_backend.views.controllers import Controller
17
 from tracim_backend.views.controllers import Controller
18
 from tracim_backend.views.core_api.schemas import ApplicationSchema
18
 from tracim_backend.views.core_api.schemas import ApplicationSchema
19
 from tracim_backend.views.core_api.schemas import ContentTypeSchema
19
 from tracim_backend.views.core_api.schemas import ContentTypeSchema
30
         """
30
         """
31
         Get list of alls applications installed in this tracim instance.
31
         Get list of alls applications installed in this tracim instance.
32
         """
32
         """
33
-        return applications
33
+        app_config = request.registry.settings['CFG']
34
+        app_api = ApplicationApi(
35
+            app_list=APP_LIST,
36
+        )
37
+        return app_api.get_all()
34
 
38
 
35
     @hapic.with_api_doc(tags=[SWAGGER_TAG_SYSTEM_ENDPOINTS])
39
     @hapic.with_api_doc(tags=[SWAGGER_TAG_SYSTEM_ENDPOINTS])
36
     @require_profile(Group.TIM_USER)
40
     @require_profile(Group.TIM_USER)

+ 2 - 2
backend/tracim_backend/views/core_api/user_controller.py View File

6
     from http import client as HTTPStatus
6
     from http import client as HTTPStatus
7
 
7
 
8
 from tracim_backend import hapic
8
 from tracim_backend import hapic
9
-from tracim_backend import TracimRequest
9
+from tracim_backend.lib.utils.request import TracimRequest
10
 from tracim_backend.models import Group
10
 from tracim_backend.models import Group
11
 from tracim_backend.lib.core.group import GroupApi
11
 from tracim_backend.lib.core.group import GroupApi
12
 from tracim_backend.lib.core.user import UserApi
12
 from tracim_backend.lib.core.user import UserApi
34
 from tracim_backend.views.core_api.schemas import ContentDigestSchema
34
 from tracim_backend.views.core_api.schemas import ContentDigestSchema
35
 from tracim_backend.views.core_api.schemas import ActiveContentFilterQuerySchema
35
 from tracim_backend.views.core_api.schemas import ActiveContentFilterQuerySchema
36
 from tracim_backend.views.core_api.schemas import WorkspaceDigestSchema
36
 from tracim_backend.views.core_api.schemas import WorkspaceDigestSchema
37
-from tracim_backend.models.contents import CONTENT_TYPES
37
+from tracim_backend.app_models.contents import CONTENT_TYPES
38
 
38
 
39
 SWAGGER_TAG__USER_ENDPOINTS = 'Users'
39
 SWAGGER_TAG__USER_ENDPOINTS = 'Users'
40
 
40
 

+ 2 - 2
backend/tracim_backend/views/core_api/workspace_controller.py View File

11
     from http import client as HTTPStatus
11
     from http import client as HTTPStatus
12
 
12
 
13
 from tracim_backend import hapic
13
 from tracim_backend import hapic
14
-from tracim_backend import TracimRequest
14
+from tracim_backend.lib.utils.request import TracimRequest
15
 from tracim_backend.lib.core.workspace import WorkspaceApi
15
 from tracim_backend.lib.core.workspace import WorkspaceApi
16
 from tracim_backend.lib.core.content import ContentApi
16
 from tracim_backend.lib.core.content import ContentApi
17
 from tracim_backend.lib.core.userworkspace import RoleApi
17
 from tracim_backend.lib.core.userworkspace import RoleApi
47
 from tracim_backend.views.core_api.schemas import WorkspaceSchema
47
 from tracim_backend.views.core_api.schemas import WorkspaceSchema
48
 from tracim_backend.views.core_api.schemas import WorkspaceIdPathSchema
48
 from tracim_backend.views.core_api.schemas import WorkspaceIdPathSchema
49
 from tracim_backend.views.core_api.schemas import WorkspaceMemberSchema
49
 from tracim_backend.views.core_api.schemas import WorkspaceMemberSchema
50
-from tracim_backend.models.contents import CONTENT_TYPES
50
+from tracim_backend.app_models.contents import CONTENT_TYPES
51
 from tracim_backend.models.revision_protection import new_revision
51
 from tracim_backend.models.revision_protection import new_revision
52
 
52
 
53
 SWAGGER_TAG_WORKSPACE_ENDPOINTS = 'Workspaces'
53
 SWAGGER_TAG_WORKSPACE_ENDPOINTS = 'Workspaces'

+ 8 - 2
backend/tracim_backend/views/frontend.py View File

2
 
2
 
3
 from pyramid.renderers import render_to_response
3
 from pyramid.renderers import render_to_response
4
 from pyramid.config import Configurator
4
 from pyramid.config import Configurator
5
+from tracim_backend.extensions import APP_LIST
5
 from tracim_backend.exceptions import PageNotFound
6
 from tracim_backend.exceptions import PageNotFound
6
-from tracim_backend.models.applications import applications
7
+from tracim_backend.lib.core.application import ApplicationApi
7
 from tracim_backend.views import BASE_API_V2
8
 from tracim_backend.views import BASE_API_V2
8
 from tracim_backend.lib.utils.request import TracimRequest
9
 from tracim_backend.lib.utils.request import TracimRequest
9
 from tracim_backend.views.controllers import Controller
10
 from tracim_backend.views.controllers import Controller
34
         app_config = request.registry.settings['CFG']
35
         app_config = request.registry.settings['CFG']
35
         # TODO - G.M - 2018-08-07 - Refactor autogen valid app list for frontend
36
         # TODO - G.M - 2018-08-07 - Refactor autogen valid app list for frontend
36
         frontend_apps = []
37
         frontend_apps = []
38
+        app_api = ApplicationApi(
39
+            app_list=APP_LIST,
40
+        )
41
+        applications = app_api.get_all()
37
         for app in applications:
42
         for app in applications:
38
             app_frontend_path = APP_FRONTEND_PATH.replace('{minislug}',
43
             app_frontend_path = APP_FRONTEND_PATH.replace('{minislug}',
39
                                                           app.minislug)  # nopep8
44
                                                           app.minislug)  # nopep8
41
                                     app_frontend_path)  # nopep8
46
                                     app_frontend_path)  # nopep8
42
             if os.path.exists(app_path):
47
             if os.path.exists(app_path):
43
                 frontend_apps.append(app)
48
                 frontend_apps.append(app)
49
+
44
         return render_to_response(
50
         return render_to_response(
45
             self._get_index_file_path(),
51
             self._get_index_file_path(),
46
             {
52
             {
47
                 'colors': {
53
                 'colors': {
48
-                    'primary': spectra.html('#7d4e24'),
54
+                    'primary': spectra.html(app_config.APPS_COLORS['primary']),
49
                 },
55
                 },
50
                 'applications': frontend_apps,
56
                 'applications': frontend_apps,
51
             }
57
             }