Browse Source

Disable ability to create empty revision from webdav and webui

Guénaël Muller 6 years ago
parent
commit
20d598ea5e

+ 39 - 35
tracim/tracim/controllers/content.py View File

174
 
174
 
175
     @property
175
     @property
176
     def _err_url(self):
176
     def _err_url(self):
177
-        return tg.url('/dashboard/workspaces/{}/folders/{}/file/{}')
177
+        return tg.url('/workspaces/{}/folders/{}/files/{}')
178
 
178
 
179
     @property
179
     @property
180
     def _item_type(self):
180
     def _item_type(self):
376
         try:
376
         try:
377
             api = ContentApi(tmpl_context.current_user)
377
             api = ContentApi(tmpl_context.current_user)
378
             item = api.get_one(int(item_id), self._item_type, workspace)
378
             item = api.get_one(int(item_id), self._item_type, workspace)
379
-            label_changed = False
380
-            if label is not None and label != item.label:
381
-                label_changed = True
382
-
383
-            if label is None:
384
-                label = ''
385
-
386
-            # TODO - D.A. - 2015-03-19
387
-            # refactor this method in order to make code easier to understand
388
 
379
 
389
             with new_revision(item):
380
             with new_revision(item):
381
+                if label:
382
+                    # This case is the default "file title and description
383
+                    # update" In this case the file itself is not revisionned
390
 
384
 
391
-                if (comment and label) or (not comment and label_changed):
385
+                    # Update description and label
392
                     updated_item = api.update_content(
386
                     updated_item = api.update_content(
393
                         item, label if label else item.label,
387
                         item, label if label else item.label,
394
                         comment if comment else ''
388
                         comment if comment else ''
401
                         return render_invalid_integrity_chosen_path(
395
                         return render_invalid_integrity_chosen_path(
402
                             updated_item.get_label_as_file(),
396
                             updated_item.get_label_as_file(),
403
                         )
397
                         )
404
-
405
                     api.save(updated_item, ActionDescription.EDITION)
398
                     api.save(updated_item, ActionDescription.EDITION)
406
-
407
-                    # This case is the default "file title and description
408
-                    # update" In this case the file itself is not revisionned
409
-
410
                 else:
399
                 else:
411
                     # So, now we may have a comment and/or a file revision
400
                     # So, now we may have a comment and/or a file revision
412
-                    if comment and '' == label:
413
-                        comment_item = api.create_comment(workspace,
414
-                                                          item, comment,
415
-                                                          do_save=False)
416
-
417
-                        if not isinstance(file_data, FieldStorage):
418
-                            api.save(comment_item, ActionDescription.COMMENT)
419
-                        else:
420
-                            # The notification is only sent
421
-                            # if the file is NOT updated
422
-                            #
423
-                            # If the file is also updated,
424
-                            # then a 'file revision' notification will be sent.
425
-                            api.save(comment_item,
426
-                                     ActionDescription.COMMENT,
427
-                                     do_notify=False)
401
+                    comment_item = None
402
+                    file_revision = None
428
 
403
 
404
+                    # INFO - G.M - 20/03/2018 - Add new comment
405
+                    if comment:
406
+                        comment_item = api.create_comment(
407
+                            workspace,
408
+                            item,
409
+                            comment,
410
+                            do_save=False
411
+                        )
412
+                    # INFO - G.M - 20/03/2018 - Add new file-revision
429
                     if isinstance(file_data, FieldStorage):
413
                     if isinstance(file_data, FieldStorage):
430
                         api.update_file_data(item,
414
                         api.update_file_data(item,
431
                                              file_data.filename,
415
                                              file_data.filename,
440
                             return render_invalid_integrity_chosen_path(
424
                             return render_invalid_integrity_chosen_path(
441
                                 item.get_label_as_file(),
425
                                 item.get_label_as_file(),
442
                             )
426
                             )
443
-
427
+                        file_revision = True
428
+
429
+                    # INFO - G.M - 20/03/2018 - Save revision/comment
430
+                    if comment_item and file_revision:
431
+                        api.save(
432
+                            comment_item,
433
+                            ActionDescription.COMMENT,
434
+                            do_notify= False
435
+                        )
436
+                        api.save(item, ActionDescription.REVISION)
437
+                    elif file_revision:
444
                         api.save(item, ActionDescription.REVISION)
438
                         api.save(item, ActionDescription.REVISION)
439
+                    elif comment_item:
440
+                        api.save(comment_item, ActionDescription.COMMENT)
445
 
441
 
446
             msg = _('{} updated').format(self._item_type_label)
442
             msg = _('{} updated').format(self._item_type_label)
447
             tg.flash(msg, CST.STATUS_OK)
443
             tg.flash(msg, CST.STATUS_OK)
449
                                              tmpl_context.folder_id,
445
                                              tmpl_context.folder_id,
450
                                              item.content_id))
446
                                              item.content_id))
451
 
447
 
448
+        except SameValueError:
449
+            not_updated = '{} not updated: the content did not change'
450
+            msg = _(not_updated).format(self._item_type_label)
451
+            tg.flash(msg, CST.STATUS_WARNING)
452
+            tg.redirect(self._err_url.format(tmpl_context.workspace_id,
453
+                                             tmpl_context.folder_id,
454
+                                             item_id))
455
+
452
         except ValueError as e:
456
         except ValueError as e:
453
             error = '{} not updated - error: {}'
457
             error = '{} not updated - error: {}'
454
             msg = _(error).format(self._item_type_label,
458
             msg = _(error).format(self._item_type_label,
459
                                              item_id))
463
                                              item_id))
460
 
464
 
461
 
465
 
466
+
462
 class UserWorkspaceFolderPageRestController(TIMWorkspaceContentRestController):
467
 class UserWorkspaceFolderPageRestController(TIMWorkspaceContentRestController):
463
     """
468
     """
464
     manage a path like this: /workspaces/1/folders/XXX/pages/4
469
     manage a path like this: /workspaces/1/folders/XXX/pages/4
606
             tg.redirect(self._std_url.format(tmpl_context.workspace_id,
611
             tg.redirect(self._std_url.format(tmpl_context.workspace_id,
607
                                              tmpl_context.folder_id,
612
                                              tmpl_context.folder_id,
608
                                              item.content_id))
613
                                              item.content_id))
609
-        except SameValueError as e:
614
+        except SameValueError:
610
             not_updated = '{} not updated: the content did not change'
615
             not_updated = '{} not updated: the content did not change'
611
             msg = _(not_updated).format(self._item_type_label)
616
             msg = _(not_updated).format(self._item_type_label)
612
             tg.flash(msg, CST.STATUS_WARNING)
617
             tg.flash(msg, CST.STATUS_WARNING)
621
                                              tmpl_context.folder_id,
626
                                              tmpl_context.folder_id,
622
                                              item_id))
627
                                              item_id))
623
 
628
 
624
-
625
 class UserWorkspaceFolderThreadRestController(TIMWorkspaceContentRestController):
629
 class UserWorkspaceFolderThreadRestController(TIMWorkspaceContentRestController):
626
     """
630
     """
627
     manage a path like this: /workspaces/1/folders/XXX/pages/4
631
     manage a path like this: /workspaces/1/folders/XXX/pages/4

+ 6 - 1
tracim/tracim/lib/content.py View File

920
 
920
 
921
     def update_content(self, item: Content, new_label: str, new_content: str=None) -> Content:
921
     def update_content(self, item: Content, new_label: str, new_content: str=None) -> Content:
922
         if item.label==new_label and item.description==new_content:
922
         if item.label==new_label and item.description==new_content:
923
-            raise SameValueError(_('The content did not changed'))
923
+            # TODO - G.M - 20-03-2018 - Fix internatization for webdav access.
924
+            # Internatization disabled in libcontent for now.
925
+            raise SameValueError('The content did not changed')
924
         item.owner = self._user
926
         item.owner = self._user
925
         item.label = new_label
927
         item.label = new_label
926
         item.description = new_content if new_content else item.description # TODO: convert urls into links
928
         item.description = new_content if new_content else item.description # TODO: convert urls into links
928
         return item
930
         return item
929
 
931
 
930
     def update_file_data(self, item: Content, new_filename: str, new_mimetype: str, new_content: bytes) -> Content:
932
     def update_file_data(self, item: Content, new_filename: str, new_mimetype: str, new_content: bytes) -> Content:
933
+        if new_mimetype == item.file_mimetype and \
934
+                new_content == item.depot_file.file.read():
935
+            raise SameValueError('The content did not changed')
931
         item.owner = self._user
936
         item.owner = self._user
932
         item.file_name = new_filename
937
         item.file_name = new_filename
933
         item.file_mimetype = new_mimetype
938
         item.file_mimetype = new_mimetype

+ 16 - 7
tracim/tracim/lib/webdav/__init__.py View File

5
 from wsgidav import compat
5
 from wsgidav import compat
6
 
6
 
7
 from tracim.lib.content import ContentApi
7
 from tracim.lib.content import ContentApi
8
+from tracim.lib.utils import SameValueError
8
 from tracim.model import new_revision
9
 from tracim.model import new_revision
9
 from tracim.model.data import ActionDescription
10
 from tracim.model.data import ActionDescription
10
 from tracim.model.data import ContentType
11
 from tracim.model.data import ContentType
11
 from tracim.model.data import Content
12
 from tracim.model.data import Content
12
 from tracim.model.data import Workspace
13
 from tracim.model.data import Workspace
14
+from wsgidav.dav_error import DAVError, HTTP_FORBIDDEN, HTTP_NOT_MODIFIED
13
 
15
 
14
 
16
 
15
 class HistoryType(object):
17
 class HistoryType(object):
96
 
98
 
97
         self._file_stream.seek(0)
99
         self._file_stream.seek(0)
98
 
100
 
99
-        if self._content is None:
100
-            self.create_file()
101
-        else:
102
-            self.update_file()
103
-
104
-        transaction.commit()
101
+        try:
102
+            if self._content is None:
103
+                self.create_file()
104
+            else:
105
+                self.update_file()
106
+            transaction.commit()
107
+        except SameValueError:
108
+            transaction.abort()
109
+            transaction.begin()
110
+            raise DAVError(HTTP_NOT_MODIFIED)
111
+        except ValueError:
112
+            transaction.abort()
113
+            transaction.begin()
114
+            raise DAVError(HTTP_FORBIDDEN)
105
 
115
 
106
     def create_file(self):
116
     def create_file(self):
107
         """
117
         """
138
                 util.guessMimeType(self._content.file_name),
148
                 util.guessMimeType(self._content.file_name),
139
                 self._file_stream.read()
149
                 self._file_stream.read()
140
             )
150
             )
141
-
142
             self._api.save(self._content, ActionDescription.REVISION)
151
             self._api.save(self._content, ActionDescription.REVISION)

+ 9 - 1
tracim/tracim/model/__init__.py View File

8
 from zope.sqlalchemy import ZopeTransactionExtension
8
 from zope.sqlalchemy import ZopeTransactionExtension
9
 
9
 
10
 from tracim.lib.exception import ContentRevisionUpdateError, ContentRevisionDeleteError
10
 from tracim.lib.exception import ContentRevisionUpdateError, ContentRevisionDeleteError
11
-
11
+from tracim.lib.utils import SameValueError
12
+import transaction
12
 
13
 
13
 class RevisionsIntegrity(object):
14
 class RevisionsIntegrity(object):
14
     """
15
     """
136
                 content.new_revision()
137
                 content.new_revision()
137
             RevisionsIntegrity.add_to_updatable(content.revision)
138
             RevisionsIntegrity.add_to_updatable(content.revision)
138
             yield content
139
             yield content
140
+        except SameValueError or ValueError as e:
141
+            # INFO - 20-03-2018 - renew transaction when error happened
142
+            # This avoid bad session data like new "temporary" revision
143
+            # to be add when problem happen.
144
+            transaction.abort()
145
+            transaction.begin()
146
+            raise e
139
         finally:
147
         finally:
140
             RevisionsIntegrity.remove_from_updatable(content.revision)
148
             RevisionsIntegrity.remove_from_updatable(content.revision)