Selaa lähdekoodia

Merge pull request #61 from tracim/fix/52_fix_sqlalchemy_issue_for_webdav

Damien Accorsi 7 vuotta sitten
vanhempi
commit
20ba34967e
No account linked to committer's email

+ 1 - 1
tracim/lib/webdav/__init__.py Näytä tiedosto

75
             WsgiDavDirBrowser,
75
             WsgiDavDirBrowser,
76
             TracimUserSession,
76
             TracimUserSession,
77
             HTTPAuthenticator,
77
             HTTPAuthenticator,
78
-            TracimEnv,
79
             ErrorPrinter,
78
             ErrorPrinter,
80
             TracimWsgiDavDebugFilter,
79
             TracimWsgiDavDebugFilter,
80
+            TracimEnv,
81
 
81
 
82
         ]
82
         ]
83
         config['provider_mapping'] = {
83
         config['provider_mapping'] = {

+ 12 - 12
tracim/lib/webdav/dav_provider.py Näytä tiedosto

68
         path = normpath(path)
68
         path = normpath(path)
69
         root_path = environ['http_authenticator.realm']
69
         root_path = environ['http_authenticator.realm']
70
 
70
 
71
-        # If the requested path is the root, then we return a Root resource
71
+        # If the requested path is the root, then we return a RootResource resource
72
         if path == root_path:
72
         if path == root_path:
73
-            return resources.Root(path, environ, user=user, session=session)
73
+            return resources.RootResource(path, environ, user=user, session=session)
74
 
74
 
75
         workspace_api = WorkspaceApi(current_user=user, session=session)
75
         workspace_api = WorkspaceApi(current_user=user, session=session)
76
         workspace = self.get_workspace_from_path(path, workspace_api)
76
         workspace = self.get_workspace_from_path(path, workspace_api)
77
 
77
 
78
-        # If the request path is in the form root/name, then we return a Workspace resource
78
+        # If the request path is in the form root/name, then we return a WorkspaceResource resource
79
         parent_path = dirname(path)
79
         parent_path = dirname(path)
80
         if parent_path == root_path:
80
         if parent_path == root_path:
81
             if not workspace:
81
             if not workspace:
82
                 return None
82
                 return None
83
-            return resources.Workspace(
83
+            return resources.WorkspaceResource(
84
                 path=path,
84
                 path=path,
85
                 environ=environ,
85
                 environ=environ,
86
                 workspace=workspace,
86
                 workspace=workspace,
107
 
107
 
108
         # Easy cases : path either end with /.deleted, /.archived or /.history, then we return corresponding resources
108
         # Easy cases : path either end with /.deleted, /.archived or /.history, then we return corresponding resources
109
         if path.endswith(SpecialFolderExtension.Archived) and self._show_archive:
109
         if path.endswith(SpecialFolderExtension.Archived) and self._show_archive:
110
-            return resources.ArchivedFolder(path, environ, workspace, content)
110
+            return resources.ArchivedFolderResource(path, environ, workspace, content)
111
 
111
 
112
         if path.endswith(SpecialFolderExtension.Deleted) and self._show_delete:
112
         if path.endswith(SpecialFolderExtension.Deleted) and self._show_delete:
113
-            return resources.DeletedFolder(path, environ, workspace, content)
113
+            return resources.DeletedFolderResource(path, environ, workspace, content)
114
 
114
 
115
         if path.endswith(SpecialFolderExtension.History) and self._show_history:
115
         if path.endswith(SpecialFolderExtension.History) and self._show_history:
116
             is_deleted_folder = re.search(r'/\.deleted/\.history$', path) is not None
116
             is_deleted_folder = re.search(r'/\.deleted/\.history$', path) is not None
120
                 else HistoryType.Archived if is_archived_folder \
120
                 else HistoryType.Archived if is_archived_folder \
121
                 else HistoryType.Standard
121
                 else HistoryType.Standard
122
 
122
 
123
-            return resources.HistoryFolder(path, environ, workspace, content, type)
123
+            return resources.HistoryFolderResource(path, environ, workspace, content, type)
124
 
124
 
125
         # Now that's more complicated, we're trying to find out if the path end with /.history/file_name
125
         # Now that's more complicated, we're trying to find out if the path end with /.history/file_name
126
         is_history_file_folder = re.search(r'/\.history/([^/]+)$', path) is not None
126
         is_history_file_folder = re.search(r'/\.history/([^/]+)$', path) is not None
127
 
127
 
128
         if is_history_file_folder and self._show_history:
128
         if is_history_file_folder and self._show_history:
129
-            return resources.HistoryFileFolder(
129
+            return resources.HistoryFileFolderResource(
130
                 path=path,
130
                 path=path,
131
                 environ=environ,
131
                 environ=environ,
132
                 content=content
132
                 content=content
143
             content = self.get_content_from_revision(content_revision, content_api)
143
             content = self.get_content_from_revision(content_revision, content_api)
144
 
144
 
145
             if content.type == ContentType.File:
145
             if content.type == ContentType.File:
146
-                return resources.HistoryFile(path, environ, content, content_revision)
146
+                return resources.HistoryFileResource(path, environ, content, content_revision)
147
             else:
147
             else:
148
                 return resources.HistoryOtherFile(path, environ, content, content_revision)
148
                 return resources.HistoryOtherFile(path, environ, content, content_revision)
149
 
149
 
153
         if content is None:
153
         if content is None:
154
             return None
154
             return None
155
         if content.type == ContentType.Folder:
155
         if content.type == ContentType.Folder:
156
-            return resources.Folder(
156
+            return resources.FolderResource(
157
                 path=path,
157
                 path=path,
158
                 environ=environ,
158
                 environ=environ,
159
                 workspace=content.workspace,
159
                 workspace=content.workspace,
162
                 user=user,
162
                 user=user,
163
             )
163
             )
164
         elif content.type == ContentType.File:
164
         elif content.type == ContentType.File:
165
-            return resources.File(
165
+            return resources.FileResource(
166
                 path=path,
166
                 path=path,
167
                 environ=environ,
167
                 environ=environ,
168
                 content=content,
168
                 content=content,
170
                 user=user
170
                 user=user
171
             )
171
             )
172
         else:
172
         else:
173
-            return resources.OtherFile(
173
+            return resources.OtherFileResource(
174
                 path=path,
174
                 path=path,
175
                 environ=environ,
175
                 environ=environ,
176
                 content=content,
176
                 content=content,

+ 209 - 84
tracim/lib/webdav/resources.py Näytä tiedosto

74
         transaction.commit()
74
         transaction.commit()
75
 
75
 
76
 
76
 
77
-class Root(DAVCollection):
77
+class RootResource(DAVCollection):
78
     """
78
     """
79
-    Root ressource that represents tracim's home, which contains all workspaces
79
+    RootResource ressource that represents tracim's home, which contains all workspaces
80
     """
80
     """
81
 
81
 
82
     def __init__(self, path: str, environ: dict, user: User, session: Session):
82
     def __init__(self, path: str, environ: dict, user: User, session: Session):
83
-        super(Root, self).__init__(path, environ)
83
+        super(RootResource, self).__init__(path, environ)
84
 
84
 
85
         self.user = user
85
         self.user = user
86
         self.session = session
86
         self.session = session
94
         )
94
         )
95
 
95
 
96
     def __repr__(self) -> str:
96
     def __repr__(self) -> str:
97
-        return '<DAVCollection: Root>'
97
+        return '<DAVCollection: RootResource>'
98
 
98
 
99
     def getMemberNames(self) -> [str]:
99
     def getMemberNames(self) -> [str]:
100
         """
100
         """
114
             workspace = self.workspace_api.get_one_by_label(label)
114
             workspace = self.workspace_api.get_one_by_label(label)
115
             workspace_path = '%s%s%s' % (self.path, '' if self.path == '/' else '/', transform_to_display(workspace.label))
115
             workspace_path = '%s%s%s' % (self.path, '' if self.path == '/' else '/', transform_to_display(workspace.label))
116
 
116
 
117
-            return Workspace(workspace_path, self.environ, workspace)
117
+            return WorkspaceResource(
118
+                workspace_path,
119
+                self.environ,
120
+                workspace,
121
+                session=self.session,
122
+                user=self.user,
123
+            )
118
         except AttributeError:
124
         except AttributeError:
119
             return None
125
             return None
120
 
126
 
146
         self.path, '' if self.path == '/' else '/', transform_to_display(new_workspace.label))
152
         self.path, '' if self.path == '/' else '/', transform_to_display(new_workspace.label))
147
 
153
 
148
         transaction.commit()
154
         transaction.commit()
149
-        return Workspace(workspace_path, self.environ, new_workspace)
155
+        return WorkspaceResource(
156
+            workspace_path,
157
+            self.environ,
158
+            new_workspace,
159
+            user=self.user,
160
+            session=self.session,
161
+        )
150
 
162
 
151
     def getMemberList(self):
163
     def getMemberList(self):
152
         """
164
         """
158
         for workspace in self.workspace_api.get_all():
170
         for workspace in self.workspace_api.get_all():
159
             workspace_path = '%s%s%s' % (self.path, '' if self.path == '/' else '/', workspace.label)
171
             workspace_path = '%s%s%s' % (self.path, '' if self.path == '/' else '/', workspace.label)
160
             members.append(
172
             members.append(
161
-                Workspace(
173
+                WorkspaceResource(
162
                     path=workspace_path,
174
                     path=workspace_path,
163
                     environ=self.environ,
175
                     environ=self.environ,
164
                     workspace=workspace,
176
                     workspace=workspace,
165
                     user=self.user,
177
                     user=self.user,
166
-                    session=self.session)
178
+                    session=self.session,
179
+                )
167
             )
180
             )
168
 
181
 
169
         return members
182
         return members
170
 
183
 
171
 
184
 
172
-class Workspace(DAVCollection):
185
+class WorkspaceResource(DAVCollection):
173
     """
186
     """
174
     Workspace resource corresponding to tracim's workspaces.
187
     Workspace resource corresponding to tracim's workspaces.
175
     Direct children can only be folders, though files might come later on and are supported
188
     Direct children can only be folders, though files might come later on and are supported
182
                  user: User,
195
                  user: User,
183
                  session: Session
196
                  session: Session
184
     ) -> None:
197
     ) -> None:
185
-        super(Workspace, self).__init__(path, environ)
198
+        super(WorkspaceResource, self).__init__(path, environ)
186
 
199
 
187
         self.workspace = workspace
200
         self.workspace = workspace
188
         self.content = None
201
         self.content = None
262
             path=self.path + '/' + file_name
275
             path=self.path + '/' + file_name
263
         )
276
         )
264
 
277
 
265
-    def createCollection(self, label: str) -> 'Folder':
278
+    def createCollection(self, label: str) -> 'FolderResource':
266
         """
279
         """
267
         Create a new folder for the current workspace. As it's not possible for the user to choose
280
         Create a new folder for the current workspace. As it's not possible for the user to choose
268
         which types of content are allowed in this folder, we allow allow all of them.
281
         which types of content are allowed in this folder, we allow allow all of them.
292
 
305
 
293
         transaction.commit()
306
         transaction.commit()
294
 
307
 
295
-        return Folder('%s/%s' % (self.path, transform_to_display(label)),
296
-                      self.environ, folder,
297
-                      self.workspace)
308
+        return FolderResource('%s/%s' % (self.path, transform_to_display(label)),
309
+                              self.environ,
310
+                              content=folder,
311
+                              session=self.session,
312
+                              user=self.user,
313
+                              workspace=self.workspace,
314
+                              )
298
 
315
 
299
     def delete(self):
316
     def delete(self):
300
         """For now, it is not possible to delete a workspace through the webdav client."""
317
         """For now, it is not possible to delete a workspace through the webdav client."""
320
 
337
 
321
             if content.type == ContentType.Folder:
338
             if content.type == ContentType.Folder:
322
                 members.append(
339
                 members.append(
323
-                    Folder(
340
+                    FolderResource(
324
                         path=content_path,
341
                         path=content_path,
325
                         environ=self.environ,
342
                         environ=self.environ,
326
                         workspace=self.workspace,
343
                         workspace=self.workspace,
332
             elif content.type == ContentType.File:
349
             elif content.type == ContentType.File:
333
                 self._file_count += 1
350
                 self._file_count += 1
334
                 members.append(
351
                 members.append(
335
-                    File(
352
+                    FileResource(
336
                         path=content_path,
353
                         path=content_path,
337
                         environ=self.environ,
354
                         environ=self.environ,
338
                         content=content,
355
                         content=content,
339
                         user=self.user,
356
                         user=self.user,
340
-                        session=self.session
357
+                        session=self.session,
341
                     )
358
                     )
342
                 )
359
                 )
343
             else:
360
             else:
344
                 self._file_count += 1
361
                 self._file_count += 1
345
-                members.append(OtherFile(content_path, self.environ, content))
362
+                members.append(
363
+                    OtherFileResource(
364
+                        content_path,
365
+                        self.environ,
366
+                        content,
367
+                        session=self.session,
368
+                        user=self.user,
369
+                    ))
346
 
370
 
347
         if self._file_count > 0 and self.provider.show_history():
371
         if self._file_count > 0 and self.provider.show_history():
348
             members.append(
372
             members.append(
349
-                HistoryFolder(
373
+                HistoryFolderResource(
350
                     path=self.path + '/' + ".history",
374
                     path=self.path + '/' + ".history",
351
                     environ=self.environ,
375
                     environ=self.environ,
352
                     content=self.content,
376
                     content=self.content,
353
                     workspace=self.workspace,
377
                     workspace=self.workspace,
354
-                    type=HistoryType.Standard
378
+                    type=HistoryType.Standard,
379
+                    session=self.session,
380
+                    user=self.user,
355
                 )
381
                 )
356
             )
382
             )
357
 
383
 
358
         if self.provider.show_delete():
384
         if self.provider.show_delete():
359
             members.append(
385
             members.append(
360
-                DeletedFolder(
386
+                DeletedFolderResource(
361
                     path=self.path + '/' + ".deleted",
387
                     path=self.path + '/' + ".deleted",
362
                     environ=self.environ,
388
                     environ=self.environ,
363
                     content=self.content,
389
                     content=self.content,
364
-                    workspace=self.workspace
390
+                    workspace=self.workspace,
391
+                    session=self.session,
392
+                    user=self.user,
365
                 )
393
                 )
366
             )
394
             )
367
 
395
 
368
         if self.provider.show_archive():
396
         if self.provider.show_archive():
369
             members.append(
397
             members.append(
370
-                ArchivedFolder(
398
+                ArchivedFolderResource(
371
                     path=self.path + '/' + ".archived",
399
                     path=self.path + '/' + ".archived",
372
                     environ=self.environ,
400
                     environ=self.environ,
373
                     content=self.content,
401
                     content=self.content,
374
-                    workspace=self.workspace
402
+                    workspace=self.workspace,
403
+                    user=self.user,
404
+                    session=self.session,
375
                 )
405
                 )
376
             )
406
             )
377
 
407
 
378
         return members
408
         return members
379
 
409
 
380
 
410
 
381
-class Folder(Workspace):
411
+class FolderResource(WorkspaceResource):
382
     """
412
     """
383
-    Folder resource corresponding to tracim's folders.
413
+    FolderResource resource corresponding to tracim's folders.
384
     Direct children can only be either folder, files, pages or threads
414
     Direct children can only be either folder, files, pages or threads
385
     By default when creating new folders, we allow them to contain all types of content
415
     By default when creating new folders, we allow them to contain all types of content
386
     """
416
     """
394
             user: User,
424
             user: User,
395
             session: Session
425
             session: Session
396
     ):
426
     ):
397
-        super(Folder, self).__init__(
427
+        super(FolderResource, self).__init__(
398
             path=path,
428
             path=path,
399
             environ=environ,
429
             environ=environ,
400
             workspace=workspace,
430
             workspace=workspace,
482
 
512
 
483
     def move_folder(self, destpath):
513
     def move_folder(self, destpath):
484
 
514
 
485
-        workspace_api = WorkspaceApi(self.user)
515
+        workspace_api = WorkspaceApi(
516
+            current_user=self.user,
517
+            session=self.session,
518
+        )
486
         workspace = self.provider.get_workspace_from_path(
519
         workspace = self.provider.get_workspace_from_path(
487
             normpath(destpath), workspace_api
520
             normpath(destpath), workspace_api
488
         )
521
         )
493
             workspace
526
             workspace
494
         )
527
         )
495
 
528
 
496
-        with new_revision(self.content):
529
+        with new_revision(
530
+            content=self.content,
531
+            tm=transaction.manager,
532
+            session=self.session,
533
+        ):
497
             if basename(destpath) != self.getDisplayName():
534
             if basename(destpath) != self.getDisplayName():
498
                 self.content_api.update_content(self.content, transform_to_bdd(basename(destpath)))
535
                 self.content_api.update_content(self.content, transform_to_bdd(basename(destpath)))
499
                 self.content_api.save(self.content)
536
                 self.content_api.save(self.content)
524
             try:
561
             try:
525
                 if content.type == ContentType.Folder:
562
                 if content.type == ContentType.Folder:
526
                     members.append(
563
                     members.append(
527
-                        Folder(
564
+                        FolderResource(
528
                             path=content_path,
565
                             path=content_path,
529
                             environ=self.environ,
566
                             environ=self.environ,
530
                             workspace=self.workspace,
567
                             workspace=self.workspace,
536
                 elif content.type == ContentType.File:
573
                 elif content.type == ContentType.File:
537
                     self._file_count += 1
574
                     self._file_count += 1
538
                     members.append(
575
                     members.append(
539
-                        File(
576
+                        FileResource(
540
                             path=content_path,
577
                             path=content_path,
541
                             environ=self.environ,
578
                             environ=self.environ,
542
                             content=content,
579
                             content=content,
546
                 else:
583
                 else:
547
                     self._file_count += 1
584
                     self._file_count += 1
548
                     members.append(
585
                     members.append(
549
-                        OtherFile(
586
+                        OtherFileResource(
550
                             path=content_path,
587
                             path=content_path,
551
                             environ=self.environ,
588
                             environ=self.environ,
552
                             content=content,
589
                             content=content,
563
 
600
 
564
         if self._file_count > 0 and self.provider.show_history():
601
         if self._file_count > 0 and self.provider.show_history():
565
             members.append(
602
             members.append(
566
-                HistoryFolder(
603
+                HistoryFolderResource(
567
                     path=self.path + '/' + ".history",
604
                     path=self.path + '/' + ".history",
568
                     environ=self.environ,
605
                     environ=self.environ,
569
                     content=self.content,
606
                     content=self.content,
570
                     workspace=self.workspace,
607
                     workspace=self.workspace,
571
-                    type=HistoryType.Standard
608
+                    type=HistoryType.Standard,
609
+                    user=self.user,
610
+                    session=self.session,
572
                 )
611
                 )
573
             )
612
             )
574
 
613
 
575
         if self.provider.show_delete():
614
         if self.provider.show_delete():
576
             members.append(
615
             members.append(
577
-                DeletedFolder(
616
+                DeletedFolderResource(
578
                     path=self.path + '/' + ".deleted",
617
                     path=self.path + '/' + ".deleted",
579
                     environ=self.environ,
618
                     environ=self.environ,
580
                     content=self.content,
619
                     content=self.content,
581
-                    workspace=self.workspace
620
+                    workspace=self.workspace,
621
+                    user=self.user,
622
+                    session=self.session,
582
                 )
623
                 )
583
             )
624
             )
584
 
625
 
585
         if self.provider.show_archive():
626
         if self.provider.show_archive():
586
             members.append(
627
             members.append(
587
-                ArchivedFolder(
628
+                ArchivedFolderResource(
588
                     path=self.path + '/' + ".archived",
629
                     path=self.path + '/' + ".archived",
589
                     environ=self.environ,
630
                     environ=self.environ,
590
                     content=self.content,
631
                     content=self.content,
591
-                    workspace=self.workspace
632
+                    workspace=self.workspace,
633
+                    user=self.user,
634
+                    session=self.session,
592
                 )
635
                 )
593
             )
636
             )
594
 
637
 
595
         return members
638
         return members
596
 
639
 
640
+# TODO - G.M - 02-05-2018 - Check these object (History/Deleted/Archived Folder)
641
+# Those object are now not in used by tracim and also not tested,
642
+
597
 
643
 
598
-class HistoryFolder(Folder):
644
+class HistoryFolderResource(FolderResource):
599
     """
645
     """
600
     A virtual resource which contains a sub-folder for every files (DAVNonCollection) contained in the parent
646
     A virtual resource which contains a sub-folder for every files (DAVNonCollection) contained in the parent
601
     folder
647
     folder
610
                  content: Content=None,
656
                  content: Content=None,
611
                  type: str=HistoryType.Standard
657
                  type: str=HistoryType.Standard
612
     ) -> None:
658
     ) -> None:
613
-        super(HistoryFolder, self).__init__(
659
+        super(HistoryFolderResource, self).__init__(
614
             path=path,
660
             path=path,
615
             environ=environ,
661
             environ=environ,
616
             workspace=workspace,
662
             workspace=workspace,
625
         self.content_api = ContentApi(
671
         self.content_api = ContentApi(
626
             current_user=self.user,
672
             current_user=self.user,
627
             show_archived=self._is_archived,
673
             show_archived=self._is_archived,
628
-            show_deleted=self._is_deleted
674
+            show_deleted=self._is_deleted,
675
+            session=self.session,
676
+            config=self.provider.app_config,
629
         )
677
         )
630
 
678
 
631
     def __repr__(self) -> str:
679
     def __repr__(self) -> str:
632
-        return "<DAVCollection: HistoryFolder (%s)>" % self.content.file_name
680
+        return "<DAVCollection: HistoryFolderResource (%s)>" % self.content.file_name
633
 
681
 
634
     def getCreationDate(self) -> float:
682
     def getCreationDate(self) -> float:
635
         return mktime(datetime.now().timetuple())
683
         return mktime(datetime.now().timetuple())
646
             content_parent=self.content
694
             content_parent=self.content
647
         )
695
         )
648
 
696
 
649
-        return HistoryFileFolder(
697
+        return HistoryFileFolderResource(
650
             path='%s/%s' % (self.path, content.get_label_as_file()),
698
             path='%s/%s' % (self.path, content.get_label_as_file()),
651
             environ=self.environ,
699
             environ=self.environ,
652
-            content=content)
700
+            content=content,
701
+            session=self.session,
702
+            user=self.user,
703
+        )
653
 
704
 
654
     def getMemberNames(self) -> [str]:
705
     def getMemberNames(self) -> [str]:
655
         ret = []
706
         ret = []
692
         
743
         
693
         for content in children:
744
         for content in children:
694
             if content.is_archived == self._is_archived and content.is_deleted == self._is_deleted:
745
             if content.is_archived == self._is_archived and content.is_deleted == self._is_deleted:
695
-                members.append(HistoryFileFolder(
746
+                members.append(HistoryFileFolderResource(
696
                     path='%s/%s' % (self.path, content.get_label_as_file()),
747
                     path='%s/%s' % (self.path, content.get_label_as_file()),
697
                     environ=self.environ,
748
                     environ=self.environ,
698
-                    content=content))
749
+                    content=content,
750
+                    user=self.user,
751
+                    session=self.session,
752
+                ))
699
 
753
 
700
         return members
754
         return members
701
 
755
 
702
 
756
 
703
-class DeletedFolder(HistoryFolder):
757
+class DeletedFolderResource(HistoryFolderResource):
704
     """
758
     """
705
     A virtual resources which exists for every folder or workspaces which contains their deleted children
759
     A virtual resources which exists for every folder or workspaces which contains their deleted children
706
     """
760
     """
714
             session: Session,
768
             session: Session,
715
             content: Content=None
769
             content: Content=None
716
     ):
770
     ):
717
-        super(DeletedFolder, self).__init__(
771
+        super(DeletedFolderResource, self).__init__(
718
             path=path,
772
             path=path,
719
             environ=environ,
773
             environ=environ,
720
             workspace=workspace,
774
             workspace=workspace,
727
         self._file_count = 0
781
         self._file_count = 0
728
 
782
 
729
     def __repr__(self):
783
     def __repr__(self):
730
-        return "<DAVCollection: DeletedFolder (%s)" % self.content.file_name
784
+        return "<DAVCollection: DeletedFolderResource (%s)" % self.content.file_name
731
 
785
 
732
     def getCreationDate(self) -> float:
786
     def getCreationDate(self) -> float:
733
         return mktime(datetime.now().timetuple())
787
         return mktime(datetime.now().timetuple())
780
                 content_path = '%s/%s' % (self.path, transform_to_display(content.get_label_as_file()))
834
                 content_path = '%s/%s' % (self.path, transform_to_display(content.get_label_as_file()))
781
 
835
 
782
                 if content.type == ContentType.Folder:
836
                 if content.type == ContentType.Folder:
783
-                    members.append(Folder(content_path, self.environ, self.workspace, content))
837
+                    members.append(
838
+                        FolderResource(
839
+                            content_path,
840
+                            self.environ,
841
+                            self.workspace,
842
+                            content,
843
+                            user=self.user,
844
+                            session=self.session,
845
+                        ))
784
                 elif content.type == ContentType.File:
846
                 elif content.type == ContentType.File:
785
                     self._file_count += 1
847
                     self._file_count += 1
786
-                    members.append(File(content_path, self.environ, content))
848
+                    members.append(
849
+                        FileResource(
850
+                            content_path,
851
+                            self.environ,
852
+                            content,
853
+                            user=self.user,
854
+                            session=self.session,
855
+                        )
856
+                    )
787
                 else:
857
                 else:
788
                     self._file_count += 1
858
                     self._file_count += 1
789
-                    members.append(OtherFile(content_path, self.environ, content))
859
+                    members.append(
860
+                        OtherFileResource(
861
+                            content_path,
862
+                            self.environ,
863
+                            content,
864
+                            user=self.user,
865
+                            session=self.session,
866
+                    ))
790
 
867
 
791
         if self._file_count > 0 and self.provider.show_history():
868
         if self._file_count > 0 and self.provider.show_history():
792
             members.append(
869
             members.append(
793
-                HistoryFolder(
870
+                HistoryFolderResource(
794
                     path=self.path + '/' + ".history",
871
                     path=self.path + '/' + ".history",
795
                     environ=self.environ,
872
                     environ=self.environ,
796
                     content=self.content,
873
                     content=self.content,
797
                     workspace=self.workspace,
874
                     workspace=self.workspace,
798
                     user=self.user,
875
                     user=self.user,
799
                     type=HistoryType.Standard,
876
                     type=HistoryType.Standard,
877
+                    session=self.session,
800
                 )
878
                 )
801
             )
879
             )
802
 
880
 
803
         return members
881
         return members
804
 
882
 
805
 
883
 
806
-class ArchivedFolder(HistoryFolder):
884
+class ArchivedFolderResource(HistoryFolderResource):
807
     """
885
     """
808
     A virtual resources which exists for every folder or workspaces which contains their archived children
886
     A virtual resources which exists for every folder or workspaces which contains their archived children
809
     """
887
     """
816
             session: Session,
894
             session: Session,
817
             content: Content=None
895
             content: Content=None
818
     ):
896
     ):
819
-        super(ArchivedFolder, self).__init__(
897
+        super(ArchivedFolderResource, self).__init__(
820
             path=path,
898
             path=path,
821
             environ=environ,
899
             environ=environ,
822
             workspace=workspace,
900
             workspace=workspace,
829
         self._file_count = 0
907
         self._file_count = 0
830
 
908
 
831
     def __repr__(self) -> str:
909
     def __repr__(self) -> str:
832
-        return "<DAVCollection: ArchivedFolder (%s)" % self.content.file_name
910
+        return "<DAVCollection: ArchivedFolderResource (%s)" % self.content.file_name
833
 
911
 
834
     def getCreationDate(self) -> float:
912
     def getCreationDate(self) -> float:
835
         return mktime(datetime.now().timetuple())
913
         return mktime(datetime.now().timetuple())
877
                 content_path = '%s/%s' % (self.path, transform_to_display(content.get_label_as_file()))
955
                 content_path = '%s/%s' % (self.path, transform_to_display(content.get_label_as_file()))
878
 
956
 
879
                 if content.type == ContentType.Folder:
957
                 if content.type == ContentType.Folder:
880
-                    members.append(Folder(content_path, self.environ, self.workspace, content))
958
+                    members.append(
959
+                        FolderResource(
960
+                            content_path,
961
+                            self.environ,
962
+                            self.workspace,
963
+                            content,
964
+                            user=self.user,
965
+                            session=self.session,
966
+                        ))
881
                 elif content.type == ContentType.File:
967
                 elif content.type == ContentType.File:
882
                     self._file_count += 1
968
                     self._file_count += 1
883
-                    members.append(File(content_path, self.environ, content))
969
+                    members.append(
970
+                        FileResource(
971
+                            content_path,
972
+                            self.environ,
973
+                            content,
974
+                            user=self.user,
975
+                            session=self.session,
976
+                        ))
884
                 else:
977
                 else:
885
                     self._file_count += 1
978
                     self._file_count += 1
886
-                    members.append(OtherFile(content_path, self.environ, content))
979
+                    members.append(
980
+                        OtherFileResource(
981
+                            content_path,
982
+                            self.environ,
983
+                            content,
984
+                            user=self.user,
985
+                            session=self.session,
986
+                        ))
887
 
987
 
888
         if self._file_count > 0 and self.provider.show_history():
988
         if self._file_count > 0 and self.provider.show_history():
889
             members.append(
989
             members.append(
890
-                HistoryFolder(
990
+                HistoryFolderResource(
891
                     path=self.path + '/' + ".history",
991
                     path=self.path + '/' + ".history",
892
                     environ=self.environ,
992
                     environ=self.environ,
893
                     content=self.content,
993
                     content=self.content,
894
                     workspace=self.workspace,
994
                     workspace=self.workspace,
895
                     user=self.user,
995
                     user=self.user,
896
-                    type=HistoryType.Standard
996
+                    type=HistoryType.Standard,
997
+                    session=self.session,
897
                 )
998
                 )
898
             )
999
             )
899
 
1000
 
900
         return members
1001
         return members
901
 
1002
 
902
 
1003
 
903
-class HistoryFileFolder(HistoryFolder):
1004
+class HistoryFileFolderResource(HistoryFolderResource):
904
     """
1005
     """
905
     A virtual resource that contains for a given content (file/page/thread) all its revisions
1006
     A virtual resource that contains for a given content (file/page/thread) all its revisions
906
     """
1007
     """
913
             user: User,
1014
             user: User,
914
             session: Session
1015
             session: Session
915
     ) -> None:
1016
     ) -> None:
916
-        super(HistoryFileFolder, self).__init__(
1017
+        super(HistoryFileFolderResource, self).__init__(
917
             path=path,
1018
             path=path,
918
             environ=environ,
1019
             environ=environ,
919
             workspace=content.workspace,
1020
             workspace=content.workspace,
924
         )
1025
         )
925
 
1026
 
926
     def __repr__(self) -> str:
1027
     def __repr__(self) -> str:
927
-        return "<DAVCollection: HistoryFileFolder (%s)" % self.content.file_name
1028
+        return "<DAVCollection: HistoryFileFolderResource (%s)" % self.content.file_name
928
 
1029
 
929
     def getDisplayName(self) -> str:
1030
     def getDisplayName(self) -> str:
930
         return self.content.get_label_as_file()
1031
         return self.content.get_label_as_file()
951
         left_side = '%s/(%d - %s) ' % (self.path, revision.revision_id, revision.revision_type)
1052
         left_side = '%s/(%d - %s) ' % (self.path, revision.revision_id, revision.revision_type)
952
 
1053
 
953
         if self.content.type == ContentType.File:
1054
         if self.content.type == ContentType.File:
954
-            return HistoryFile(
1055
+            return HistoryFileResource(
955
                 path='%s%s' % (left_side, transform_to_display(revision.file_name)),
1056
                 path='%s%s' % (left_side, transform_to_display(revision.file_name)),
956
                 environ=self.environ,
1057
                 environ=self.environ,
957
                 content=self.content,
1058
                 content=self.content,
958
-                content_revision=revision)
1059
+                content_revision=revision,
1060
+                session=self.session,
1061
+                user=self.user,
1062
+            )
959
         else:
1063
         else:
960
             return HistoryOtherFile(
1064
             return HistoryOtherFile(
961
                 path='%s%s' % (left_side, transform_to_display(revision.get_label_as_file())),
1065
                 path='%s%s' % (left_side, transform_to_display(revision.get_label_as_file())),
962
                 environ=self.environ,
1066
                 environ=self.environ,
963
                 content=self.content,
1067
                 content=self.content,
964
-                content_revision=revision)
1068
+                content_revision=revision,
1069
+                session=self.session,
1070
+                user=self.user,
1071
+            )
965
 
1072
 
966
     def getMemberList(self) -> [_DAVResource]:
1073
     def getMemberList(self) -> [_DAVResource]:
967
         members = []
1074
         members = []
971
             left_side = '%s/(%d - %s) ' % (self.path, content.revision_id, content.revision_type)
1078
             left_side = '%s/(%d - %s) ' % (self.path, content.revision_id, content.revision_type)
972
 
1079
 
973
             if self.content.type == ContentType.File:
1080
             if self.content.type == ContentType.File:
974
-                members.append(HistoryFile(
1081
+                members.append(HistoryFileResource(
975
                     path='%s%s' % (left_side, transform_to_display(content.file_name)),
1082
                     path='%s%s' % (left_side, transform_to_display(content.file_name)),
976
                     environ=self.environ,
1083
                     environ=self.environ,
977
                     content=self.content,
1084
                     content=self.content,
978
-                    content_revision=content)
1085
+                    content_revision=content,
1086
+                    user=self.user,
1087
+                    session=self.session,
1088
+                    )
979
                 )
1089
                 )
980
             else:
1090
             else:
981
                 members.append(HistoryOtherFile(
1091
                 members.append(HistoryOtherFile(
982
                     path='%s%s' % (left_side, transform_to_display(content.file_name)),
1092
                     path='%s%s' % (left_side, transform_to_display(content.file_name)),
983
                     environ=self.environ,
1093
                     environ=self.environ,
984
                     content=self.content,
1094
                     content=self.content,
985
-                    content_revision=content)
1095
+                    content_revision=content,
1096
+                    user=self.user,
1097
+                    session=self.session,
1098
+                    )
986
                 )
1099
                 )
987
 
1100
 
988
         return members
1101
         return members
989
 
1102
 
990
 
1103
 
991
-class File(DAVNonCollection):
1104
+class FileResource(DAVNonCollection):
992
     """
1105
     """
993
-    File resource corresponding to tracim's files
1106
+    FileResource resource corresponding to tracim's files
994
     """
1107
     """
995
     def __init__(
1108
     def __init__(
996
             self,
1109
             self,
1000
             user: User,
1113
             user: User,
1001
             session: Session,
1114
             session: Session,
1002
     ) -> None:
1115
     ) -> None:
1003
-        super(File, self).__init__(path, environ)
1116
+        super(FileResource, self).__init__(path, environ)
1004
 
1117
 
1005
         self.content = content
1118
         self.content = content
1006
         self.user = user
1119
         self.user = user
1016
         # self.setPropertyValue('Win32FileAttributes', '00000021')
1129
         # self.setPropertyValue('Win32FileAttributes', '00000021')
1017
 
1130
 
1018
     def __repr__(self) -> str:
1131
     def __repr__(self) -> str:
1019
-        return "<DAVNonCollection: File (%d)>" % self.content.revision_id
1132
+        return "<DAVNonCollection: FileResource (%d)>" % self.content.revision_id
1020
 
1133
 
1021
     def getContentLength(self) -> int:
1134
     def getContentLength(self) -> int:
1022
         return self.content.depot_file.file.content_length
1135
         return self.content.depot_file.file.content_length
1230
         ).action()
1343
         ).action()
1231
 
1344
 
1232
 
1345
 
1233
-class HistoryFile(File):
1346
+class HistoryFileResource(FileResource):
1234
     """
1347
     """
1235
     A virtual resource corresponding to a specific tracim's revision's file
1348
     A virtual resource corresponding to a specific tracim's revision's file
1236
     """
1349
     """
1237
     def __init__(self, path: str, environ: dict, content: Content, user: User, session: Session, content_revision: ContentRevisionRO):
1350
     def __init__(self, path: str, environ: dict, content: Content, user: User, session: Session, content_revision: ContentRevisionRO):
1238
-        super(HistoryFile, self).__init__(path, environ, content, user=user, session=session)
1351
+        super(HistoryFileResource, self).__init__(path, environ, content, user=user, session=session)
1239
         self.content_revision = content_revision
1352
         self.content_revision = content_revision
1240
 
1353
 
1241
     def __repr__(self) -> str:
1354
     def __repr__(self) -> str:
1242
-        return "<DAVNonCollection: HistoryFile (%s-%s)" % (self.content.content_id, self.content.file_name)
1355
+        return "<DAVNonCollection: HistoryFileResource (%s-%s)" % (self.content.content_id, self.content.file_name)
1243
 
1356
 
1244
     def getDisplayName(self) -> str:
1357
     def getDisplayName(self) -> str:
1245
         left_side = '(%d - %s) ' % (self.content_revision.revision_id, self.content_revision.revision_type)
1358
         left_side = '(%d - %s) ' % (self.content_revision.revision_id, self.content_revision.revision_type)
1268
         raise DAVError(HTTP_FORBIDDEN)
1381
         raise DAVError(HTTP_FORBIDDEN)
1269
 
1382
 
1270
 
1383
 
1271
-class OtherFile(File):
1384
+class OtherFileResource(FileResource):
1272
     """
1385
     """
1273
-    File resource corresponding to tracim's page and thread
1386
+    FileResource resource corresponding to tracim's page and thread
1274
     """
1387
     """
1275
     def __init__(self, path: str, environ: dict, content: Content, user:User, session: Session):
1388
     def __init__(self, path: str, environ: dict, content: Content, user:User, session: Session):
1276
-        super(OtherFile, self).__init__(path, environ, content, user=user, session=session)
1389
+        super(OtherFileResource, self).__init__(path, environ, content, user=user, session=session)
1277
 
1390
 
1278
         self.content_revision = self.content.revision
1391
         self.content_revision = self.content.revision
1279
 
1392
 
1292
         return self.path
1405
         return self.path
1293
 
1406
 
1294
     def __repr__(self) -> str:
1407
     def __repr__(self) -> str:
1295
-        return "<DAVNonCollection: OtherFile (%s)" % self.content.file_name
1408
+        return "<DAVNonCollection: OtherFileResource (%s)" % self.content.file_name
1296
 
1409
 
1297
     def getContentLength(self) -> int:
1410
     def getContentLength(self) -> int:
1298
         return len(self.content_designed)
1411
         return len(self.content_designed)
1318
             )
1431
             )
1319
 
1432
 
1320
 
1433
 
1321
-class HistoryOtherFile(OtherFile):
1434
+class HistoryOtherFile(OtherFileResource):
1322
     """
1435
     """
1323
     A virtual resource corresponding to a specific tracim's revision's page and thread
1436
     A virtual resource corresponding to a specific tracim's revision's page and thread
1324
     """
1437
     """
1325
-    def __init__(self, path: str, environ: dict, content: Content, user:User, content_revision: ContentRevisionRO):
1326
-        super(HistoryOtherFile, self).__init__(path, environ, content, user=user, session=self.session)
1438
+    def __init__(self,
1439
+                 path: str,
1440
+                 environ: dict,
1441
+                 content: Content,
1442
+                 user:User,
1443
+                 content_revision: ContentRevisionRO,
1444
+                 session: Session):
1445
+        super(HistoryOtherFile, self).__init__(
1446
+            path,
1447
+            environ,
1448
+            content,
1449
+            user=user,
1450
+            session=session
1451
+        )
1327
         self.content_revision = content_revision
1452
         self.content_revision = content_revision
1328
         self.content_designed = self.design()
1453
         self.content_designed = self.design()
1329
 
1454
 

+ 14 - 1
tracim/models/__init__.py Näytä tiedosto

48
 
48
 
49
     """
49
     """
50
     dbsession = session_factory()
50
     dbsession = session_factory()
51
+    # FIXME - G.M - 02-05-2018 - Check Zope/Sqlalchemy session conf.
52
+    # We use both keep_session=True for zope and
53
+    # expire_on_commit=False for sessionmaker to keep session alive after
54
+    # commit ( in order  to not have trouble like
55
+    # https://github.com/tracim/tracim_backend/issues/52
56
+    # or detached objects problems).
57
+    # These problem happened because we use "commit" in our current code.
58
+    # Understand what those params really mean and check if it can cause
59
+    # troubles somewhere else.
60
+    # see https://stackoverflow.com/questions/16152241/how-to-get-a-sqlalchemy-session-managed-by-zope-transaction-that-has-the-same-sc  # nopep8
51
     zope.sqlalchemy.register(
61
     zope.sqlalchemy.register(
52
-        dbsession, transaction_manager=transaction_manager)
62
+        dbsession,
63
+        transaction_manager=transaction_manager,
64
+        keep_session=True,
65
+    )
53
     listen(dbsession, 'before_flush', prevent_content_revision_delete)
66
     listen(dbsession, 'before_flush', prevent_content_revision_delete)
54
     return dbsession
67
     return dbsession
55
 
68
 

+ 9 - 13
tracim/tests/library/test_webdav.py Näytä tiedosto

8
 from tracim.tests import eq_
8
 from tracim.tests import eq_
9
 from tracim.lib.core.notifications import DummyNotifier
9
 from tracim.lib.core.notifications import DummyNotifier
10
 from tracim.lib.webdav.dav_provider import Provider
10
 from tracim.lib.webdav.dav_provider import Provider
11
-from tracim.lib.webdav.resources import Root
11
+from tracim.lib.webdav.resources import RootResource
12
 from tracim.models import Content
12
 from tracim.models import Content
13
 from tracim.models import ContentRevisionRO
13
 from tracim.models import ContentRevisionRO
14
 from tracim.tests import StandardTest
14
 from tracim.tests import StandardTest
88
                 'bob@fsf.local',
88
                 'bob@fsf.local',
89
             )
89
             )
90
         )
90
         )
91
-        assert root, 'Path / should return a Root instance'
92
-        assert isinstance(root, Root)
91
+        assert root, 'Path / should return a RootResource instance'
92
+        assert isinstance(root, RootResource)
93
 
93
 
94
     def test_unit__list_workspaces_with_user__ok(self):
94
     def test_unit__list_workspaces_with_user__ok(self):
95
         provider = self._get_provider(self.app_config)
95
         provider = self._get_provider(self.app_config)
100
                 'bob@fsf.local',
100
                 'bob@fsf.local',
101
             )
101
             )
102
         )
102
         )
103
-        assert root, 'Path / should return a Root instance'
104
-        assert isinstance(root, Root), 'Path / should return a Root instance'
103
+        assert root, 'Path / should return a RootResource instance'
104
+        assert isinstance(root, RootResource), 'Path / should return a RootResource instance'
105
 
105
 
106
         children = root.getMemberList()
106
         children = root.getMemberList()
107
         eq_(
107
         eq_(
108
             2,
108
             2,
109
             len(children),
109
             len(children),
110
-            msg='Root should return 2 workspaces instead {0}'.format(
110
+            msg='RootResource should return 2 workspaces instead {0}'.format(
111
                 len(children),
111
                 len(children),
112
             )
112
             )
113
         )
113
         )
130
                 'admin@admin.admin',
130
                 'admin@admin.admin',
131
             )
131
             )
132
         )
132
         )
133
-        assert root, 'Path / should return a Root instance'
134
-        assert isinstance(root, Root), 'Path / should return a Root instance'
133
+        assert root, 'Path / should return a RootResource instance'
134
+        assert isinstance(root, RootResource), 'Path / should return a RootResource instance'
135
 
135
 
136
         children = root.getMemberList()
136
         children = root.getMemberList()
137
         eq_(
137
         eq_(
138
             2,
138
             2,
139
             len(children),
139
             len(children),
140
-            msg='Root should return 2 workspaces instead {0}'.format(
140
+            msg='RootResource should return 2 workspaces instead {0}'.format(
141
                 len(children),
141
                 len(children),
142
             )
142
             )
143
         )
143
         )
311
             )
311
             )
312
         )
312
         )
313
 
313
 
314
-    @pytest.mark.xfail(raises=InvalidRequestError,
315
-                       reason='Sqlalchemy session and transaction bug')
316
     def test_unit__create_delete_and_create_file__ok(self):
314
     def test_unit__create_delete_and_create_file__ok(self):
317
         provider = self._get_provider(self.app_config)
315
         provider = self._get_provider(self.app_config)
318
         environ = self._get_environ(
316
         environ = self._get_environ(
559
                 content_to_move.parent.label
557
                 content_to_move.parent.label
560
         )
558
         )
561
 
559
 
562
-    @pytest.mark.xfail(raises=InvalidRequestError,
563
-                       reason='Sqlalchemy session and transaction bug')
564
     def test_unit__update_content__ok(self):
560
     def test_unit__update_content__ok(self):
565
         provider = self._get_provider(self.app_config)
561
         provider = self._get_provider(self.app_config)
566
         environ = self._get_environ(
562
         environ = self._get_environ(