Browse Source

do not create content if not allowed

Guénaël Muller 6 years ago
parent
commit
94b6796776

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

@@ -203,3 +203,7 @@ class PageOfPreviewNotFound(NotFound):
203 203
 
204 204
 class PreviewDimNotAllowed(TracimException):
205 205
     pass
206
+
207
+
208
+class UnallowedSubContent(TracimException):
209
+    pass

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

@@ -25,7 +25,7 @@ from sqlalchemy.sql.elements import and_
25 25
 
26 26
 from tracim_backend.lib.utils.utils import cmp_to_key
27 27
 from tracim_backend.lib.core.notifications import NotifierFactory
28
-from tracim_backend.exceptions import SameValueError
28
+from tracim_backend.exceptions import SameValueError, UnallowedSubContent
29 29
 from tracim_backend.exceptions import PageOfPreviewNotFound
30 30
 from tracim_backend.exceptions import PreviewDimNotAllowed
31 31
 from tracim_backend.exceptions import RevisionDoesNotMatchThisContent
@@ -408,13 +408,31 @@ class ContentApi(object):
408 408
 
409 409
     def create(self, content_type_slug: str, workspace: Workspace, parent: Content=None, label: str = '', filename: str = '', do_save=False, is_temporary: bool=False, do_notify=True) -> Content:
410 410
         # TODO - G.M - 2018-07-16 - raise Exception instead of assert
411
-        assert content_type_slug in CONTENT_TYPES.query_allowed_types_slugs()
412 411
         assert content_type_slug != CONTENT_TYPES.Any_SLUG
413 412
         assert not (label and filename)
414 413
 
415 414
         if content_type_slug == CONTENT_TYPES.Folder.slug and not label:
416 415
             label = self.generate_folder_label(workspace, parent)
417 416
 
417
+        if not workspace:
418
+            workspace = parent.workspace
419
+
420
+        content_type = CONTENT_TYPES.get_one_by_slug(content_type_slug)
421
+        if parent:
422
+            if content_type.slug not in parent.properties['allowed_content'] or not parent.properties['allowed_content'][content_type.slug]:
423
+                raise UnallowedSubContent(' SubContent of type {subcontent_type}  not allowed in content {content_id}'.format(  # nopep8
424
+                    subcontent_type=content_type.slug,
425
+                    content_id=parent.content_id,
426
+                ))
427
+
428
+        if content_type.slug not in workspace.get_allowed_content_types():
429
+            raise UnallowedSubContent(
430
+                ' SubContent of type {subcontent_type}  not allowed in workspace {content_id}'.format(  # nopep8
431
+                    subcontent_type=content_type.slug,
432
+                    content_id=workspace.workspace_id,
433
+                )
434
+            )
435
+
418 436
         content = Content()
419 437
 
420 438
         if filename:
@@ -433,8 +451,9 @@ class ContentApi(object):
433 451
 
434 452
         content.owner = self._user
435 453
         content.parent = parent
454
+
436 455
         content.workspace = workspace
437
-        content.type = content_type_slug
456
+        content.type = content_type.slug
438 457
         content.is_temporary = is_temporary
439 458
         content.revision_type = ActionDescription.CREATION
440 459
 
@@ -450,6 +469,7 @@ class ContentApi(object):
450 469
         return content
451 470
 
452 471
     def create_comment(self, workspace: Workspace=None, parent: Content=None, content:str ='', do_save=False) -> Content:
472
+        # TODO: check parent allowed_type and workspace allowed_ type
453 473
         assert parent and parent.type != CONTENT_TYPES.Folder.slug
454 474
         if not content:
455 475
             raise EmptyCommentContentNotAllowed()

+ 1 - 0
backend/tracim_backend/models/contents.py View File

@@ -228,6 +228,7 @@ class ContentTypeList(object):
228 228
         """
229 229
         content_types = self._content_types.copy()
230 230
         content_types.extend(self._special_contents_types)
231
+        content_types.append(self.Event)
231 232
         for item in content_types:
232 233
             if item.slug == slug or (item.slug_alias and slug in item.slug_alias):  # nopep8
233 234
                 return item

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

@@ -87,7 +87,7 @@ class Workspace(DeclarativeBase):
87 87
 
88 88
     def get_allowed_content_types(self):
89 89
         # @see Content.get_allowed_content_types()
90
-        return CONTENT_TYPES.endpoint_allowed_types_slug()
90
+        return CONTENT_TYPES.extended_endpoint_allowed_types_slug()
91 91
 
92 92
     def get_valid_children(
93 93
             self,

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

@@ -9,7 +9,8 @@ from tracim_backend.lib.core.content import ContentApi
9 9
 # TODO - G.M - 28-03-2018 - [GroupApi] Re-enable GroupApi
10 10
 from tracim_backend.lib.core.group import GroupApi
11 11
 from tracim_backend.lib.core.user import UserApi
12
-from tracim_backend.exceptions import SameValueError
12
+from tracim_backend.exceptions import SameValueError, EmptyLabelNotAllowed, \
13
+    UnallowedSubContent
13 14
 # TODO - G.M - 28-03-2018 - [RoleApi] Re-enable RoleApi
14 15
 from tracim_backend.lib.core.workspace import RoleApi
15 16
 # TODO - G.M - 28-03-2018 - [WorkspaceApi] Re-enable WorkspaceApi
@@ -101,6 +102,181 @@ class TestContentApi(DefaultTest):
101 102
             'value is {} instead of {}'.format(sorteds[1].content_id,
102 103
                                                c1.content_id))
103 104
 
105
+    def test_unit__create_content__OK_nominal_case(self):
106
+        uapi = UserApi(
107
+            session=self.session,
108
+            config=self.app_config,
109
+            current_user=None,
110
+        )
111
+        group_api = GroupApi(
112
+            current_user=None,
113
+            session=self.session,
114
+            config=self.app_config,
115
+        )
116
+        groups = [group_api.get_one(Group.TIM_USER),
117
+                  group_api.get_one(Group.TIM_MANAGER),
118
+                  group_api.get_one(Group.TIM_ADMIN)]
119
+
120
+        user = uapi.create_minimal_user(email='this.is@user',
121
+                                        groups=groups, save_now=True)
122
+        workspace = WorkspaceApi(
123
+            current_user=user,
124
+            session=self.session,
125
+            config=self.app_config,
126
+        ).create_workspace('test workspace', save_now=True)
127
+        api = ContentApi(
128
+            current_user=user,
129
+            session=self.session,
130
+            config=self.app_config,
131
+        )
132
+        item = api.create(
133
+            content_type_slug=CONTENT_TYPES.Folder.slug,
134
+            workspace=workspace,
135
+            parent=None,
136
+            label='not_deleted',
137
+            do_save=True
138
+        )
139
+        assert isinstance(item, Content)
140
+
141
+    def test_unit__create_content__err_empty_label(self):
142
+        uapi = UserApi(
143
+            session=self.session,
144
+            config=self.app_config,
145
+            current_user=None,
146
+        )
147
+        group_api = GroupApi(
148
+            current_user=None,
149
+            session=self.session,
150
+            config=self.app_config,
151
+        )
152
+        groups = [group_api.get_one(Group.TIM_USER),
153
+                  group_api.get_one(Group.TIM_MANAGER),
154
+                  group_api.get_one(Group.TIM_ADMIN)]
155
+
156
+        user = uapi.create_minimal_user(email='this.is@user',
157
+                                        groups=groups, save_now=True)
158
+        workspace = WorkspaceApi(
159
+            current_user=user,
160
+            session=self.session,
161
+            config=self.app_config,
162
+        ).create_workspace('test workspace', save_now=True)
163
+        api = ContentApi(
164
+            current_user=user,
165
+            session=self.session,
166
+            config=self.app_config,
167
+        )
168
+        with pytest.raises(EmptyLabelNotAllowed):
169
+            api.create(
170
+                content_type_slug=CONTENT_TYPES.Thread.slug,
171
+                workspace=workspace,
172
+                parent=None,
173
+                label='',
174
+                do_save=True
175
+            )
176
+
177
+    def test_unit__create_content__err_content_type_not_allowed_in_this_folder(self):
178
+        uapi = UserApi(
179
+            session=self.session,
180
+            config=self.app_config,
181
+            current_user=None,
182
+        )
183
+        group_api = GroupApi(
184
+            current_user=None,
185
+            session=self.session,
186
+            config=self.app_config,
187
+        )
188
+        groups = [group_api.get_one(Group.TIM_USER),
189
+                  group_api.get_one(Group.TIM_MANAGER),
190
+                  group_api.get_one(Group.TIM_ADMIN)]
191
+
192
+        user = uapi.create_minimal_user(email='this.is@user',
193
+                                        groups=groups, save_now=True)
194
+        workspace = WorkspaceApi(
195
+            current_user=user,
196
+            session=self.session,
197
+            config=self.app_config,
198
+        ).create_workspace('test workspace', save_now=True)
199
+        api = ContentApi(
200
+            current_user=user,
201
+            session=self.session,
202
+            config=self.app_config,
203
+        )
204
+        folder = api.create(
205
+            content_type_slug=CONTENT_TYPES.Folder.slug,
206
+            workspace=workspace,
207
+            parent=None,
208
+            label='plop',
209
+            do_save=False
210
+        )
211
+        allowed_content_dict = {CONTENT_TYPES.Folder.slug: True, CONTENT_TYPES.File.slug: False} # nopep8
212
+        api.set_allowed_content(
213
+            folder,
214
+            allowed_content_dict=allowed_content_dict
215
+        )
216
+        api.save(content=folder)
217
+        # not in list -> do not allow
218
+        with pytest.raises(UnallowedSubContent):
219
+            api.create(
220
+                content_type_slug=CONTENT_TYPES.Event.slug,
221
+                workspace=workspace,
222
+                parent=folder,
223
+                label='lapin',
224
+                do_save=True
225
+            )
226
+        # in list but false -> do not allow
227
+        with pytest.raises(UnallowedSubContent):
228
+            api.create(
229
+                content_type_slug=CONTENT_TYPES.File.slug,
230
+                workspace=workspace,
231
+                parent=folder,
232
+                label='lapin',
233
+                do_save=True
234
+            )
235
+        # in list and true -> allow
236
+        api.create(
237
+            content_type_slug=CONTENT_TYPES.Folder.slug,
238
+            workspace=workspace,
239
+            parent=folder,
240
+            label='lapin',
241
+            do_save=True
242
+        )
243
+
244
+    def test_unit__create_content__err_content_type_not_allowed_in_this_workspace(self):
245
+        uapi = UserApi(
246
+            session=self.session,
247
+            config=self.app_config,
248
+            current_user=None,
249
+        )
250
+        group_api = GroupApi(
251
+            current_user=None,
252
+            session=self.session,
253
+            config=self.app_config,
254
+        )
255
+        groups = [group_api.get_one(Group.TIM_USER),
256
+                  group_api.get_one(Group.TIM_MANAGER),
257
+                  group_api.get_one(Group.TIM_ADMIN)]
258
+
259
+        user = uapi.create_minimal_user(email='this.is@user',
260
+                                        groups=groups, save_now=True)
261
+        workspace = WorkspaceApi(
262
+            current_user=user,
263
+            session=self.session,
264
+            config=self.app_config,
265
+        ).create_workspace('test workspace', save_now=True)
266
+        api = ContentApi(
267
+            current_user=user,
268
+            session=self.session,
269
+            config=self.app_config,
270
+        )
271
+        with pytest.raises(UnallowedSubContent):
272
+            api.create(
273
+                content_type_slug=CONTENT_TYPES.Event.slug,
274
+                workspace=workspace,
275
+                parent=None,
276
+                label='lapin',
277
+                do_save=True
278
+            )
279
+
104 280
     def test_delete(self):
105 281
         uapi = UserApi(
106 282
             session=self.session,