Browse Source

correction of some bugs with moving objects and first revision of readme

Nonolost 8 years ago
parent
commit
388d9e07b4

+ 49 - 0
tracim/tracim/lib/webdav/README.txt View File

@@ -0,0 +1,49 @@
1
+## What is webdav ?
2
+
3
+Webdav's a extension of the HTTP protocol that introduces new requests (MKCOL, PROPFIND...) to ease the
4
+management of files on a distant server. More information can be found [here](https://tools.ietf.org/html/rfc4918).
5
+
6
+This project is based on the project [WSGIDav](https://github.com/mar10/wsgidav), which is an implementation of webdav in python that
7
+provides all basic needs to install a webdav on your server. This library intends to adapt WSGIDav implementation
8
+with the database based file management of Tracim, allowing users to access and modify files through their
9
+Window's file system.
10
+
11
+## Behavior to know about Windows' client and Webdav
12
+
13
+There are behaviors you may observe while using the windows' client for webdav which differ from other clients.
14
+
15
+* Window's will send twice each request. The first one as Anonymous, which will get a 401 Not Authorized, and then
16
+the second authentified which will proceed normally. This is the correct behavior that you have to observe for every webdav's client.
17
+In fact when sending
18
+The thing is that you'll observe only one request for clients like Debian's default filesystem because they cache the first response
19
+they got when sending an Anonymous request and they know that they have to send an authentication, thus they don't waste time sending
20
+twice the request.
21
+
22
+* When uploading new documents, windows will call twice put if the files does not exist. The first one with a length of 0 so that the resources
23
+can be locked before sending the whole file.
24
+
25
+* To display names, Windows won't use the displayName property but the object's path. Thus even if /a/b/c can link to a file named 'readme.txt' with
26
+   other webdav's client, you'll need to have a path named '/a/b/readme.txt' with Windows' client.
27
+
28
+## Known issues
29
+
30
+As for now, there's still some flaws or unexpected behaviors in the webdav implementation when using Windows' client.
31
+Though we could - and may - use github's issues to report them, we'll first write them down here to not pollute the
32
+original reports on tracim's _normal use_.
33
+
34
+* When moving files or folders from webdav to webdav, windows will warn you that this action may harm your computer. Though it won't say anything
35
+when moving files from your computer to webdav or vice-versa.
36
+
37
+* When deleting folders, Windows will go through all sub-folders and files recursively and request to delete them itself before going back to the main
38
+target. In our case it means it'll delete all sub-contents in database when we only want the parent to be in _deleted state_.
39
+Plus as a folder is _never empty_ (always contains .deleted and .archived) it won't even delete the folder because it'll first check if the target
40
+isn't empty before sending the final delete request.
41
+
42
+* Lock/unlock system is currently broken, thus it's not possible to work with office as it'll lock both the document and its temporary files and
43
+will be unable to unlock afterward, making it impossible to update them and making windows make a lot of unwanted request because the first failed.
44
+**Imma gonna correct it asap**.
45
+
46
+## Improving performances
47
+
48
+All request aren't still optimal and may take longer than what we want or expect. Here will be some tracks that will ease
49
+code refactoring to improve performances.

+ 6 - 1
tracim/tracim/lib/webdav/sql_dav_provider.py View File

@@ -49,6 +49,9 @@ class Provider(DAVProvider):
49 49
         """
50 50
         Called by wsgidav whenever a request is called to get the _DAVResource corresponding to the path
51 51
         """
52
+        if not self.exists(path, environ):
53
+            return None
54
+
52 55
         path = normpath(path)
53 56
         root_path = environ['http_authenticator.realm']
54 57
 
@@ -63,6 +66,8 @@ class Provider(DAVProvider):
63 66
         # If the request path is in the form root/name, then we return a Workspace resource
64 67
         parent_path = dirname(path)
65 68
         if parent_path == root_path:
69
+            if not workspace:
70
+                return None
66 71
             return sql_resources.Workspace(path, environ, workspace)
67 72
 
68 73
         # And now we'll work on the path to establish which type or resource is requested
@@ -151,7 +156,7 @@ class Provider(DAVProvider):
151 156
 
152 157
         workspace = self.get_workspace_from_path(path, WorkspaceApi(user))
153 158
 
154
-        if parent_path == root_path:
159
+        if parent_path == root_path or workspace is None:
155 160
             return workspace is not None
156 161
 
157 162
         content_api = ContentApi(user, show_archived=True, show_deleted=True)

+ 32 - 26
tracim/tracim/lib/webdav/sql_resources.py View File

@@ -199,6 +199,7 @@ class Workspace(DAVCollection):
199 199
         return self.workspace.label
200 200
 
201 201
     def getLastModified(self) -> float:
202
+        print("hm....", self.path)
202 203
         return mktime(self.workspace.updated.timetuple())
203 204
 
204 205
     def getMemberNames(self) -> [str]:
@@ -579,10 +580,11 @@ class HistoryFolder(Folder):
579 580
             children = self.content_api.get_all(None, ContentType.Any, self.workspace)
580 581
         
581 582
         for content in children:
582
-            members.append(HistoryFileFolder(
583
-                path='%s/%s' % (self.path, content.get_label()),
584
-                environ=self.environ,
585
-                content=content))
583
+            if content.is_archived == self._is_archived and content.is_deleted == self._is_deleted:
584
+                members.append(HistoryFileFolder(
585
+                    path='%s/%s' % (self.path, content.get_label()),
586
+                    environ=self.environ,
587
+                    content=content))
586 588
 
587 589
         return members
588 590
 
@@ -647,16 +649,17 @@ class DeletedFolder(HistoryFolder):
647 649
             children = self.content_api.get_all(None, ContentType.Any, self.workspace)
648 650
 
649 651
         for content in children:
650
-            content_path = '%s/%s' % (self.path, self.provider.transform_to_display(content.get_label()))
652
+            if content.is_deleted:
653
+                content_path = '%s/%s' % (self.path, self.provider.transform_to_display(content.get_label()))
651 654
 
652
-            if content.type == ContentType.Folder:
653
-                members.append(Folder(content_path, self.environ, self.workspace, content))
654
-            elif content.type == ContentType.File:
655
-                self._file_count += 1
656
-                members.append(File(content_path, self.environ, content))
657
-            else:
658
-                self._file_count += 1
659
-                members.append(OtherFile(content_path, self.environ, content))
655
+                if content.type == ContentType.Folder:
656
+                    members.append(Folder(content_path, self.environ, self.workspace, content))
657
+                elif content.type == ContentType.File:
658
+                    self._file_count += 1
659
+                    members.append(File(content_path, self.environ, content))
660
+                else:
661
+                    self._file_count += 1
662
+                    members.append(OtherFile(content_path, self.environ, content))
660 663
 
661 664
         if self._file_count > 0 and self.provider.show_history():
662 665
             members.append(
@@ -726,16 +729,17 @@ class ArchivedFolder(HistoryFolder):
726 729
             children = self.content_api.get_all(None, ContentType.Any, self.workspace)
727 730
 
728 731
         for content in children:
729
-            content_path = '%s/%s' % (self.path, self.provider.transform_to_display(content.get_label()))
732
+            if content.is_archived:
733
+                content_path = '%s/%s' % (self.path, self.provider.transform_to_display(content.get_label()))
730 734
 
731
-            if content.type == ContentType.Folder:
732
-                members.append(Folder(content_path, self.environ, self.workspace, content))
733
-            elif content.type == ContentType.File:
734
-                self._file_count += 1
735
-                members.append(File(content_path, self.environ, content))
736
-            else:
737
-                self._file_count += 1
738
-                members.append(OtherFile(content_path, self.environ, content))
735
+                if content.type == ContentType.Folder:
736
+                    members.append(Folder(content_path, self.environ, self.workspace, content))
737
+                elif content.type == ContentType.File:
738
+                    self._file_count += 1
739
+                    members.append(File(content_path, self.environ, content))
740
+                else:
741
+                    self._file_count += 1
742
+                    members.append(OtherFile(content_path, self.environ, content))
739 743
 
740 744
         if self._file_count > 0 and self.provider.show_history():
741 745
             members.append(
@@ -932,17 +936,19 @@ class File(DAVNonCollection):
932 936
             raise DAVError(HTTP_FORBIDDEN)
933 937
 
934 938
     def move_file(self, destpath):
935
-        parent = self.provider.get_parent_from_path(
939
+
940
+        workspace = self.provider.get_workspace_from_path(
936 941
             normpath(destpath),
937
-            self.content_api,
938 942
             WorkspaceApi(self.user)
939 943
         )
940 944
 
941
-        workspace = self.provider.get_workspace_from_path(
945
+        parent = self.provider.get_parent_from_path(
942 946
             normpath(destpath),
943
-            WorkspaceApi(self.user)
947
+            self.content_api,
948
+            workspace
944 949
         )
945 950
 
951
+
946 952
         with new_revision(self.content):
947 953
             if basename(destpath) != self.getDisplayName():
948 954
                 self.content_api.update_content(self.content, re.sub('\.[^\.]+$', '', self.provider.transform_to_bdd(basename(destpath))))