Browse Source

Correction of few bugs on windows/debian client and some code refactoring

Nonolost 8 years ago
parent
commit
63162bbe8f

+ 1 - 1
install/requirements.txt View File

@@ -59,7 +59,7 @@ unicode-slugify==0.1.3
59 59
 vobject==0.9.2
60 60
 waitress==0.8.9
61 61
 who-ldap==3.1.0
62
--e git+git@github.com:mar10/wsgidav.git@b95354f17ec57133c656f470ca3933a3bd54f524#egg=wsgidav
62
+-e git+git@github.com:Nonolost/wsgidav.git@73f832e6bd94ac21ae608af43a9516ff31abc9a2#egg=wsgidav
63 63
 zope.interface==4.1.3
64 64
 zope.sqlalchemy==0.7.6
65 65
 

+ 1 - 1
tracim/tracim/controllers/root.py View File

@@ -144,7 +144,7 @@ class RootController(StandardController):
144 144
         # - last activity
145 145
         # - oldest open stuff
146 146
 
147
-        items = ContentApi(user).get_all(None, ContentType.Any, None)[:4]
147
+        items = ContentApi(user).get_all_without_exception(ContentType.Any, None)[:4]
148 148
         fake_api.favorites = Context(CTX.CONTENT_LIST).toDict(items, 'contents', 'nb')
149 149
         return DictLikeClass(fake_api=fake_api)
150 150
 

+ 8 - 4
tracim/tracim/lib/content.py View File

@@ -396,9 +396,13 @@ class ContentApi(object):
396 396
         try:
397 397
             return resultset.filter(Content.label == content_label).one()
398 398
         except:
399
-            return resultset.filter(Content.file_name == content_label).one()
399
+            try:
400
+                return resultset.filter(Content.file_name == content_label).one()
401
+            except:
402
+                import re
403
+                return resultset.filter(Content.label == re.sub(r'\.[^.]+$', '', content_label)).one()
400 404
 
401
-    def get_all(self, parent_id: int, content_type: str, workspace: Workspace=None) -> [Content]:
405
+    def get_all(self, parent_id: int=None, content_type: str=ContentType.Any, workspace: Workspace=None) -> [Content]:
402 406
         assert parent_id is None or isinstance(parent_id, int) # DYN_REMOVE
403 407
         assert content_type is not None# DYN_REMOVE
404 408
         assert isinstance(content_type, str) # DYN_REMOVE
@@ -412,10 +416,10 @@ class ContentApi(object):
412 416
 
413 417
         return resultset.all()
414 418
 
415
-    def get_all_without_exception(self, content_type: str) -> [Content]:
419
+    def get_all_without_exception(self, content_type: str, workspace: Workspace=None) -> [Content]:
416 420
         assert content_type is not None# DYN_REMOVE
417 421
 
418
-        resultset = self._base_query(None)
422
+        resultset = self._base_query(workspace)
419 423
 
420 424
         if content_type != ContentType.Any:
421 425
             resultset = resultset.filter(Content.type==content_type)

+ 17 - 11
tracim/tracim/lib/daemons.py View File

@@ -230,6 +230,9 @@ from wsgidav.xml_tools import useLxml
230 230
 from wsgidav.wsgidav_app import WsgiDAVApp
231 231
 from wsgidav._version import __version__
232 232
 
233
+from tracim.lib.webdav.sql_dav_provider import Provider
234
+from tracim.lib.webdav.sql_domain_controller import SQLDomainController
235
+
233 236
 from inspect import isfunction
234 237
 import traceback
235 238
 
@@ -252,21 +255,25 @@ class WsgiDavDaemon(Daemon):
252 255
 
253 256
         # Configuration file overrides defaults
254 257
         config_file = os.path.abspath(DEFAULT_CONFIG_FILE)
255
-        if config_file:
256
-            fileConf = self._readConfigFile(config_file, temp_verbose)
257
-            config.update(fileConf)
258
-        else:
259
-            if temp_verbose >= 2:
260
-                print("Running without configuration file.")
258
+        fileConf = self._readConfigFile(config_file, temp_verbose)
259
+        config.update(fileConf)
261 260
 
262 261
         if not useLxml and config["verbose"] >= 1:
263 262
             print(
264 263
                 "WARNING: Could not import lxml: using xml instead (slower). Consider installing lxml from http://codespeak.net/lxml/.")
265 264
 
266
-        if not config["provider_mapping"]:
267
-            print("ERROR: No DAV provider defined. Try --help option.", file=sys.stderr)
268
-            sys.exit(-1)
269
-
265
+        config['provider_mapping'] = \
266
+            {
267
+                config['root_path']: Provider(
268
+                    show_archived=config['show_archived'],
269
+                    show_deleted=config['show_deleted'],
270
+                    show_history=config['show_history'],
271
+                    manage_locks=config['manager_locks']
272
+                )
273
+            }
274
+
275
+        config['domaincontroller'] = SQLDomainController(presetdomain=None, presetserver=None)
276
+        config['defaultdigest'] = False
270 277
         return config
271 278
 
272 279
     def _readConfigFile(self, config_file, verbose):
@@ -336,7 +343,6 @@ class WsgiDavDaemon(Daemon):
336 343
 
337 344
     def stop(self):
338 345
         self._server.stop()
339
-        print("WsgiDav : je m'arrête")
340 346
 
341 347
     def append_thread_callback(self, callback: collections.Callable) -> None:
342 348
         """

+ 51 - 26
tracim/tracim/lib/webdav/__init__.py View File

@@ -2,7 +2,7 @@ from wsgidav.compat import to_bytes
2 2
 
3 3
 from tracim.lib.content import ContentApi
4 4
 from tracim.model import new_revision
5
-from tracim.model.data import ActionDescription, ContentType, Content
5
+from tracim.model.data import ActionDescription, ContentType, Content, Workspace
6 6
 from wsgidav import util
7 7
 
8 8
 import transaction
@@ -14,52 +14,77 @@ class HistoryType(object):
14 14
     All = 'all'
15 15
 
16 16
 
17
-class FileStream(object):
18
-    def __init__(self, file_name: str, content: Content, content_api: ContentApi, new_file: bool):
17
+class FakeFileStream(object):
18
+    """Fake a FileStream object that is needed by wsgidav to create or update existing files
19
+    with new content"""
20
+
21
+    def __init__(self, content_api: ContentApi, workspace: Workspace,
22
+                 file_name: str='', content: Content=None, parent: Content=None):
23
+        """
24
+
25
+        :param file_name: the filename if the file is new
26
+        :param content_api:
27
+        :param workspace: content's workspace, necessary if the file is new as we've got no other way to get it
28
+        :param content: either the content to be updated or None if it's a new file
29
+        """
19 30
         self._buffer = []
20 31
         self._file_name = file_name if file_name != '' else self._content.file_name
21 32
         self._content = content
22 33
         self._api = content_api
23
-        self._is_new_file = new_file
34
+        self._workspace = workspace
35
+        self._parent = parent
24 36
 
25
-    def beginWrite(self, contentType) -> 'FileStream':
37
+    def beginWrite(self, contentType) -> 'FakeFileStream':
38
+        """Called by request_server to user as a file stream to write bits by bits content into a filestream"""
26 39
         return self
27 40
 
28 41
     def endWrite(self, withErrors: bool):
42
+        """Called by request_server when finished writing everythin, wdc"""
29 43
         pass
30 44
 
31 45
     def write(self, s: str):
46
+        """Called by request_server when writing content to files, we stock it in our file"""
32 47
         self._buffer.append(s)
33 48
 
34 49
     def close(self):
50
+        """Called by request_server when everything has been written and we either update the file or
51
+        create a new file"""
35 52
         item_content = b''
36 53
 
37 54
         for part in self._buffer:
38 55
             item_content += part
39 56
 
40
-        if self._is_new_file:
41
-            file = self._api.create(
42
-                content_type=ContentType.File,
43
-                workspace=self._content.workspace,
44
-                parent=self._content
45
-                )
57
+        if self._content is None:
58
+            self.create_file(item_content)
59
+        else:
60
+            self.update_file(item_content)
61
+
62
+    def create_file(self, item_content):
63
+        file = self._api.create(
64
+            content_type=ContentType.File,
65
+            workspace=self._workspace,
66
+            parent=self._parent
67
+            )
68
+
69
+        self._api.update_file_data(
70
+            file,
71
+            self._file_name,
72
+            util.guessMimeType(self._file_name),
73
+            item_content
74
+        )
46 75
 
76
+        self._api.save(file, ActionDescription.CREATION)
77
+
78
+        transaction.commit()
79
+
80
+    def update_file(self, item_content: bytes):
81
+        with new_revision(self._content):
47 82
             self._api.update_file_data(
48
-                file,
83
+                self._content,
49 84
                 self._file_name,
50
-                util.guessMimeType(self._file_name),
85
+                util.guessMimeType(self._content.file_name),
51 86
                 item_content
52
-                )
87
+            )
88
+            self._api.save(self._content, ActionDescription.EDITION)
53 89
 
54
-            self._api.save(file, ActionDescription.CREATION)
55
-
56
-        else:
57
-            with new_revision(self._content):
58
-                self._api.update_file_data(
59
-                    self._content,
60
-                    self._file_name,
61
-                    util.guessMimeType(self._content.file_name),
62
-                    item_content)
63
-                self._api.save(self._content, ActionDescription.EDITION)
64
-
65
-        transaction.commit()
90
+        transaction.commit()

+ 87 - 333
tracim/tracim/lib/webdav/sql_dav_provider.py View File

@@ -30,19 +30,21 @@ def wsgi_encode(s):
30 30
     return s.encode().decode('latin1')
31 31
 
32 32
 
33
+
34
+
33 35
 # ============================================================
34 36
 # PostgreSQLProvider
35 37
 # ============================================================
36 38
 class Provider(DAVProvider):
37
-    def __init__(self, manage_lock=True):
39
+    def __init__(self, show_history=True, show_deleted=True, show_archived=True, manage_locks=True):
38 40
         super(Provider, self).__init__()
39 41
 
40
-        if manage_lock:
42
+        if manage_locks:
41 43
             self.lockManager = LockManager(LockStorage())
42 44
 
43
-        self._show_archive = True
44
-        self._show_delete = True
45
-        self._show_history = True
45
+        self._show_archive = show_archived
46
+        self._show_delete = show_deleted
47
+        self._show_history = show_history
46 48
 
47 49
     def show_history(self):
48 50
         return self._show_history
@@ -61,8 +63,15 @@ class Provider(DAVProvider):
61 63
     def getResourceInst(self, path, environ):
62 64
         #if not self.exists(path, environ):
63 65
         #    return None
66
+        if not self.exists(path, environ):
67
+            return None
68
+
69
+        uapi = UserApi(None)
70
+        environ['user'] = uapi.get_one_by_email(environ['http_authenticator.username'])
64 71
 
65 72
         norm_path = normpath(path)
73
+        norm_path = self.transform_to_display(norm_path)
74
+
66 75
         root_path = environ['http_authenticator.realm']
67 76
         parent_path = dirname(norm_path)
68 77
 
@@ -101,6 +110,7 @@ class Provider(DAVProvider):
101 110
                 path=norm_path,
102 111
                 environ=environ,
103 112
                 content=content,
113
+                workspace=self.get_workspace_from_path(norm_path, workspace_api)
104 114
             )
105 115
 
106 116
         # is delete
@@ -110,7 +120,8 @@ class Provider(DAVProvider):
110 120
             return sql_resources.DeletedFolder(
111 121
                 path=norm_path,
112 122
                 environ=environ,
113
-                content=content
123
+                content=content,
124
+                workspace=self.get_workspace_from_path(norm_path, workspace_api)
114 125
             )
115 126
 
116 127
         # is history
@@ -128,7 +139,8 @@ class Provider(DAVProvider):
128 139
                 path=norm_path,
129 140
                 environ=environ,
130 141
                 content=content,
131
-                type=type
142
+                type=type,
143
+                workspace=self.get_workspace_from_path(norm_path, workspace_api)
132 144
             )
133 145
 
134 146
         # is history
@@ -154,16 +166,21 @@ class Provider(DAVProvider):
154 166
                 return sql_resources.HistoryOtherFile(path, environ, content, content_revision)
155 167
 
156 168
         # other
169
+        if content is None:
170
+            return None
157 171
         if content.type == ContentType.Folder:
158
-            return sql_resources.Folder(path, environ, content)
172
+            return sql_resources.Folder(path, environ, content, content.workspace)
159 173
         elif content.type == ContentType.File:
160
-            return sql_resources.File(path, environ, content, False)
174
+            return sql_resources.File(path, environ, content)
161 175
         elif content.type in [ContentType.Page, ContentType.Thread]:
162 176
             return sql_resources.OtherFile(path, environ, content)
163 177
         else:
164 178
             return None
165 179
 
166 180
     def exists(self, path, environ):
181
+        uapi = UserApi(None)
182
+        environ['user'] = uapi.get_one_by_email(environ['http_authenticator.username'])
183
+
167 184
         norm_path = normpath(path)
168 185
         parent_path = dirname(norm_path)
169 186
         root_path = environ['http_authenticator.realm']
@@ -176,16 +193,12 @@ class Provider(DAVProvider):
176 193
         )
177 194
 
178 195
         if path == root_path:
179
-            return sql_resources.Root(path, environ)
196
+            return True
180 197
         elif parent_path == root_path:
181
-            return sql_resources.Workspace(
182
-                path=norm_path,
183
-                environ=environ,
184
-                workspace=self.get_workspace_from_path(
198
+            return self.get_workspace_from_path(
185 199
                     norm_path,
186 200
                     workspace_api
187
-                )
188
-            ) is not None
201
+                ) is not None
189 202
 
190 203
         is_archived = re.search(r'/\.archived/(\.history/)?(?!\.history)[^/]*(/\.)?(history|deleted|archived)?$', norm_path) is not None
191 204
 
@@ -193,6 +206,10 @@ class Provider(DAVProvider):
193 206
 
194 207
         revision_id = re.search(r'/\.history/[^/]+/(\d+)-([^/].+)$', norm_path)
195 208
 
209
+        blbl = self.reduce_path(norm_path)
210
+        if dirname(blbl) == '/':
211
+            return self.get_workspace_from_path(norm_path, workspace_api) is not None
212
+
196 213
         if revision_id:
197 214
             revision_id = revision_id.group(1)
198 215
             content = content_api.get_one_revision(revision_id)
@@ -217,18 +234,18 @@ class Provider(DAVProvider):
217 234
 
218 235
         workspace = self.get_workspace_from_path(path, workspace_api)
219 236
 
220
-        if basename(dirname(path)) == workspace.label:
221
-            try:
222
-                return content_api.get_one_by_label_and_parent(basename(path), workspace=workspace)
223
-            except:
237
+        try:
238
+            if basename(dirname(path)) == workspace.label:
239
+                return content_api.get_one_by_label_and_parent(
240
+                    self.transform_to_bdd(basename(path)),
241
+                    workspace=workspace
242
+                )
243
+            else:
244
+                parent = self.get_parent_from_path(path, content_api, workspace_api)
245
+                if parent is not None:
246
+                    return content_api.get_one_by_label_and_parent(self.transform_to_bdd(basename(path)), content_parent=parent)
224 247
                 return None
225
-        else:
226
-            parent = self.get_parent_from_path(path, content_api, workspace_api)
227
-            if parent is not None:
228
-                try:
229
-                    return content_api.get_one_by_label_and_parent(basename(path), content_parent=parent)
230
-                except:
231
-                    return None
248
+        except:
232 249
             return None
233 250
 
234 251
     def get_content_from_revision(self, revision: ContentRevisionRO, api:ContentApi):
@@ -238,320 +255,53 @@ class Provider(DAVProvider):
238 255
             return None
239 256
 
240 257
     def get_parent_from_path(self, path, api: ContentApi, workspace_api: WorkspaceApi):
258
+
241 259
         return self.get_content_from_path(dirname(path), api, workspace_api)
242 260
 
243 261
     def get_workspace_from_path(self, path: str, api: WorkspaceApi):
244 262
         assert path.startswith('/')
245 263
 
246
-        print(path)
247 264
         try:
248
-            return api.get_one_by_label(path.split('/')[1])
265
+            return api.get_one_by_label(self.transform_to_bdd(path.split('/')[1]))
249 266
         except:
250 267
             return None
251 268
 
252
-    #########################################################
253
-    # Everything that transform path
254
-    '''
255
-    def from_id_to_name(self, path):
256
-        path_ret = ''
257
-
258
-        for item_id in path.split('/'):
259
-            if item_id == '':
260
-                pass
261
-            elif path_ret == '':
262
-                path_ret += '/' + self.get_workspace({'workspace_id': item_id}).label
263
-            else:
264
-                path_ret += '/' + self.get_item({'id': item_id}).item_name
265
-
266
-        return path_ret
267
-
268
-    def from_name_to_id(self, path):
269
-        if path == '/':
270
-            return '/'
271
-        path_ret = ""
272
-        last_id = None
273
-        workspace_id = None
274
-
275
-        for item_name in path.split("/"):
276
-            if item_name == '':
277
-                pass
278
-            elif path_ret == '':
279
-                workspace = self.get_workspace({'label': item_name})
280
-                if workspace is None:
281
-                    return None
282
-
283
-                workspace_id = workspace.workspace_id
284
-                path_ret += '/' + str(workspace_id)
285
-            else:
286
-                item = self.get_item(
287
-                    {
288
-                        'parent_id': last_id,
289
-                        'item_name': item_name,
290
-                        'workspace_id': workspace_id,
291
-                        'child_revision_id': None
292
-                    }
293
-                )
294
-
295
-                if item is None:
296
-                    return None
297
-
298
-                last_id = item.id
299
-                path_ret += '/' + str(last_id)
300
-
301
-        return path_ret
302
-
303
-    #########################################################
304
-    # Everything that check things (lol) ...
305
-    def has_right(self, username, workspace_id, expected=0):
306
-        ret = self.session.query(UserRoleInWorkspace.role).filter(
307
-            UserRoleInWorkspace.workspace_id == workspace_id,
308
-            User.user_id == UserRoleInWorkspace.user_id,
309
-            User.display_name == username
310
-        ).one_or_none()
311
-
312
-        return ret is not None and role[ret.role] >= expected
313
-
314
-    def exist_revision(self, item_name, item_id):
315
-        return self.get_item({'id': item_id, 'item_name': item_name}) is not None
316
-
317
-    @staticmethod
318
-    def is_history(path):
319
-        return normpath(path).endswith('.history')
320
-
321
-    #########################################################
322
-    # Everything that goes with "delete"
323
-    def delete_item(self, element):
324
-        self.session.delete(element)
325
-        self.session.commit()
326
-
327
-    #########################################################
328
-    # Everything that goes with "add"
329
-    def add_item(self, item_name, item_type, workspace_id, parent_id=None, parent_revision_id=None,
330
-                 child_revision_id=None, item_content=None, created=None, updated=None):
331
-
332
-        item = ItemRevision(
333
-            item_name=to_unicode(item_name),
334
-            item_type=to_unicode(item_type),
335
-            item_content=item_content,
336
-            workspace_id=workspace_id,
337
-            parent_id=parent_id,
338
-            created=created,
339
-            updated=updated,
340
-            parent_revision_id=parent_revision_id,
341
-            child_revision_id=child_revision_id
342
-        )
343
-
344
-        self.session.add(item)
345
-        self.session.commit()
346
-
347
-        return item
348
-
349
-    def add_workspace(self, environ, label):
350
-        workspace = Workspace(label=label)
351
-
352
-        self.session.add(workspace)
353
-
354
-        user = self.get_user_with_name(environ['http_authenticator.username'])
355
-
356
-        user_workspace = UserRoleInWorkspace(
357
-            role='WORKSPACE_MANAGER',
358
-            workspace_id=workspace.workspace_id,
359
-            user_id=user.user_id
360
-        )
361
-
362
-        self.session.add(user_workspace)
363
-        self.session.commit()
364
-
365
-        return workspace
366
-
367
-    #########################################################
368
-    # Everything that goes with "set"
369
-    def set_workspace_label(self, workspace, label):
370
-        workspace.label = label
371
-        self.session.commit()
372
-
373
-    #########################################################
374
-    # Everything that goes with "get"
375
-    def get_all_revisions_from_item(self, item, only_id=False):
376
-        ret = []
377
-        current_item = item
378
-        while current_item is not None:
379
-            if only_id:
380
-                ret.insert(0,current_item.id)
381
-            else:
382
-                ret.insert(0,current_item)
383
-
384
-            current_item = self.get_item(
385
-                {
386
-                    'child_revision_id': current_item.id
387
-                }
388
-            )
389
-
390
-        return ret
391
-
392
-    def get_item(self, keys_dict):
393
-        query = self.session.query(ItemRevision)
394
-
395
-        for key, value in keys_dict.items():
396
-            query = query.filter(getattr(ItemRevision, key) == value)
397
-        return query.first()
398
-
399
-    def get_item_children(self, item_id):
400
-        items_result = self.session.query(ItemRevision.id).filter(
401
-            ItemRevision.parent_id == item_id,
402
-            ItemRevision.child_revision_id.is_(None)
403
-        )
404
-
405
-        ret_id = []
406
-        for item in items_result:
407
-            ret_id.append(item.id)
408
-
409
-        return ret_id
410
-
411
-    def get_workspace_id_from_path(self, path):
412
-        return int(self.get_id_from_path('/' + path.split('/')[1]))
413
-
414
-    def get_workspace_children_id(self, workspace):
415
-        items_result = self.session.query(ItemRevision.id).filter(
416
-            ItemRevision.parent_id.is_(None),
417
-            ItemRevision.workspace_id == workspace.workspace_id
418
-        )
419
-
420
-        ret = []
421
-        for item in items_result:
422
-            ret.append(item.id)
423
-
424
-        return ret
425
-
426
-    # on workspaces
427
-    def get_workspace(self, keys_dict):
428
-        query = self.session.query(Workspace)
429
-
430
-        for key, value in keys_dict.items():
431
-            query = query.filter(getattr(Workspace, key) == value)
432
-        return query.one_or_none()
433
-
434
-    def get_all_workspaces(self, only_name=False):
435
-        retlist = []
436
-        for workspace in self.session.query(Workspace).all():
437
-            if only_name:
438
-                retlist.append(workspace.label)
439
-            else:
440
-                retlist.append(workspace)
441
-
442
-        return retlist
443
-
444
-    # on users
445
-    def get_user_with_name(self, username):
446
-        return self.session.query(User).filter(
447
-            User.display_name == username
448
-        ).one_or_none()
449
-
450
-    # on path
451
-    def get_id_from_path(self, path):
452
-        path_id = self.from_name_to_id(path)
453
-
454
-        if path_id == '/':
455
-            return None
456
-        else:
457
-            return int(basename(path_id))
458
-
459
-    def get_parent_id_from_path(self, path):
460
-        return self.get_id_from_path(dirname(path))
461
-
462
-    #########################################################
463
-    # Everything that goes with "move"
464
-    def move_item(self, item, destpath):
465
-        path = normpath(destpath)
466
-
467
-        if dirname(dirname(path)) == '/':
468
-            new_parent = None
469
-        else:
470
-            new_parent = self.get_parent_id_from_path(path)
471
-
472
-        item.parent_id = new_parent
473
-        item.workspace_id = self.get_workspace_id_from_path(path)
474
-        item.item_name = basename(path)
475
-        self.session.commit()
476
-
477
-    def move_all_revisions(self, item, destpath):
478
-        path = normpath(destpath)
479
-        new_parent = self.get_parent_id_from_path(path)
480
-        new_workspace = self.get_workspace_id_from_path(destpath)
481
-
482
-        items = self.get_all_revisions_from_item(item)
483
-
484
-        for current_item in items:
485
-            current_item.parent_id = new_parent
486
-            current_item.workspace_id = new_workspace
487
-
488
-        new_name = basename(normpath(destpath))
489
-
490
-        new_item = self.add_item(
491
-            item_name=new_name,
492
-            item_type=item.item_type,
493
-            workspace_id=item.workspace_id,
494
-            parent_id=item.parent_id,
495
-            parent_revision_id=item.id,
496
-            child_revision_id=None,
497
-            item_content=item.item_content,
498
-            created=item.created,
499
-            updated=datetime.now()
500
-        )
501
-
502
-        item.child_revision_id = new_item.id
503
-
504
-        self.session.commit()
505
-
506
-    #########################################################
507
-    # Everything that goes with "copy"
508
-    def copy_item(self, item, destpath):
509
-        path = normpath(destpath)
510
-
511
-        new_parent = self.get_parent_id_from_path(path)
512
-        new_workspace = self.get_workspace_id_from_path(path)
513
-        items = self.get_all_revisions_from_item(item)
514
-
515
-        first = True
516
-        last_item = None
517
-
518
-        for current_item in items:
519
-            new_item = self.add_item(
520
-                item_name=current_item.item_name,
521
-                item_type=current_item.item_type,
522
-                workspace_id=new_workspace,
523
-                parent_id=new_parent,
524
-                parent_revision_id=None,
525
-                child_revision_id=None,
526
-                item_content=current_item.item_content,
527
-                created=current_item.created,
528
-                updated=current_item.updated
529
-            )
530
-
531
-            if not first:
532
-                last_item.child_revision_id = new_item.id
533
-                new_item.parent_revision_id = last_item.id
534
-
535
-            first = False
536
-            last_item = new_item
537
-
538
-        new_name = basename(destpath)
539
-        
540
-        new_item = self.add_item(
541
-            item_name=new_name,
542
-            item_type=item.item_type,
543
-            workspace_id=new_workspace,
544
-            parent_id=new_parent,
545
-            parent_revision_id=last_item.id,
546
-            child_revision_id=None,
547
-            item_content=item.item_content,
548
-            created=datetime.now(),
549
-            updated=datetime.now()
550
-        )
551
-
552
-        last_item.child_revision_id = new_item.id
269
+    def transform_to_display(self, string):
270
+        _TO_DISPLAY = {
271
+            # '/':'⁄',
272
+            '\\': '⧹',
273
+            ':': '∶',
274
+            '*': '∗',
275
+            '?': 'ʔ',
276
+            '"': 'ʺ',
277
+            '<': '❮',
278
+            '>': '❯',
279
+            '|': '∣'
280
+        }
281
+
282
+        for key, value in _TO_DISPLAY.items():
283
+            string = string.replace(key, value)
284
+
285
+        return string
286
+
287
+    def transform_to_bdd(self, string):
288
+        _TO_BDD = {
289
+            # '⁄': '/',
290
+            '⧹': '\\',
291
+            '∶': ':',
292
+            '∗': '*',
293
+            'ʔ': '?',
294
+            'ʺ': '"',
295
+            '❮': '<',
296
+            '❯': '>',
297
+            '∣': '|'
298
+        }
299
+
300
+        for key, value in _TO_BDD.items():
301
+            string = string.replace(key, value)
302
+
303
+        return string
553 304
 
554
-        self.session.commit()'''
555 305
 
556 306
 """
557 307
 
@@ -597,8 +347,12 @@ class Provider(DAVProvider):
597 347
      'ext_servers': ['cherrypy-bundled', 'wsgidav']
598 348
  },
599 349
  'http_authenticator.realm': '/',
600
- 'HTTP_AUTHORIZATION': 'Digest username="admin@admin.admin", realm="/", nonce="=", uri="/nouveau/", algorithm=MD5, response="9c78c484263409b3385ead95ea7bf65b", '
601
-                       'cnonce="MHgyMzNkZjkwOjQ4OTU6MTQ2OTc3OTI1NQ==", nc=00000471, qop=auth',
350
+ 'HTTP_AUTHORIZATION': 'Digest username="admin@admin.admin",
351
+ realm="/", nonce="=",
352
+ uri="/nouveau/",
353
+ algorithm=MD5,
354
+ response="9c78c484263409b3385ead95ea7bf65b", '
355
+ 'cnonce="MHgyMzNkZjkwOjQ4OTU6MTQ2OTc3OTI1NQ==", nc=00000471, qop=auth',
602 356
  'HTTP_ACCEPT_ENCODING': 'gzip, deflate',
603 357
  'HTTP_USER_AGENT': 'gvfs/1.22.2', 'wsgidav.debug_break': False,
604 358
  'HTTP_CONNECTION': 'Keep-Alive', 'SERVER_PORT': '3030', 'CONTENT_LENGTH': '235', 'HTTP_HOST': '127.0.0.1:3030', 'REQUEST_METHOD': 'PROPFIND', 'HTTP_APPLY_TO_REDIRECT_REF': 'T', 'SERVER_NAME': 'WsgiDAV/3.0.0pre1 CherryPy/3.2.4 Python/3.4.2', 'wsgi.errors': <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>, 'wsgi.url_scheme': 'http', 'user': <User: email='admin@admin.admin', display='Global manager'>, 'HTTP_ACCEPT_LANGUAGE': 'en-us, en;q=0.9', 'ACTUAL_SERVER_PROTOCOL': 'HTTP/1.1', 'REMOTE_PORT': '48375', 'CONTENT_TYPE': 'application/xml', 'SCRIPT_NAME': '', 'wsgi.input': <wsgidav.server.cherrypy.wsgiserver.wsgiserver3.KnownLengthRFile object at 0x7fbc8410ce48>, 'wsgidav.username': 'admin@admin.admin', 'http_authenticator.username': 'admin@admin.admin', 'wsgidav.provider': Provider, 'PATH_INFO': '/nouveau/', 'HTTP_DEPTH': '1', 'SERVER_SOFTWARE': 'WsgiDAV/3.0.0pre1 CherryPy/3.2.4 Python/3.4.2 Server'}

+ 1 - 2
tracim/tracim/lib/webdav/sql_domain_controller.py View File

@@ -21,7 +21,7 @@ class SQLDomainController(object):
21 21
         travailler dans la bdd pour vérifier si utilisateur existe
22 22
         """
23 23
         try:
24
-            environ['user'] = self._api.get_one_by_email(username)
24
+            self._api.get_one_by_email(username)
25 25
             return True
26 26
         except:
27 27
             return False
@@ -30,7 +30,6 @@ class SQLDomainController(object):
30 30
         """Retourne le mdp pour l'utilisateur pour ce real"""
31 31
         try:
32 32
             user = self._api.get_one_by_email(username)
33
-            return 'test'
34 33
             return user.password
35 34
         except:
36 35
             return None

File diff suppressed because it is too large
+ 494 - 465
tracim/tracim/lib/webdav/sql_resources.py


+ 9 - 160
tracim/wsgidav.conf.sample View File

@@ -1,33 +1,12 @@
1 1
 ################################################################################
2 2
 # Sample WsgiDAV configuration file
3
-# 
3
+#
4 4
 # 1. Rename this file to `wsgidav.conf`
5 5
 # 2. Adjust settings as appropriate
6
-# 3. Run `wsgidav` fro, the same directory.
7
-#
8
-# See
9
-#     doc/annotated_wsgidav.conf
10
-# for a complete, annotated configuration example.
6
+# 3. Run tracim as you always do :)
11 7
 #
12 8
 ################################################################################
13 9
 
14
-# HELPERS - Do not modify this section
15
-
16
-provider_mapping = {}
17
-user_mapping = {}
18
-
19
-def addShare(shareName, davProvider):
20
-    provider_mapping[shareName] = davProvider
21
-
22
-    
23
-def addUser(realmName, user, password, description, roles=[]):
24
-    realmName = "/" + realmName.strip(r"\/")
25
-    userDict = user_mapping.setdefault(realmName, {}).setdefault(user, {})
26
-    userDict["password"] = password
27
-    userDict["description"] = description
28
-    userDict["roles"] = roles
29
-
30
-        
31 10
 ################################################################################
32 11
 # SERVER OPTIONS
33 12
 #===============================================================================
@@ -36,149 +15,19 @@ def addUser(realmName, user, password, description, roles=[]):
36 15
 # host  = "192.168.0.1"
37 16
 host  = "0.0.0.0"
38 17
 
39
-port = 8080
40
-
41
-#===============================================================================
42
-# Enable SSL support
43
-# (The certificate should match the servers hostname, so the bogus certs will not
44
-# work in all scenarios.)
45
-
46
-# ssl_certificate = "wsgidav/server/sample_bogo_server.crt"
47
-# ssl_private_key = "wsgidav/server/sample_bogo_server.key"
48
-# ssl_certificate_chain = None
49
-
50
-
51
-# Add the MS-Author-Via Response Header to OPTIONS command to allow editing
52
-# with Microsoft Office (default: True)
53
-add_header_MS_Author_Via = True	
54
-
55
-#================================================================================
56
-# Misc. setings
57
-#
58
-
59
-# Block size in bytes
60
-#block_size = 8192
61
-
62
-#===============================================================================
63
-# Middlewares
64
-# 
65
-# Use this section to modify the default middleware stack
66
-
67
-#from wsgidav.dir_browser import WsgiDavDirBrowser
68
-#from debug_filter import WsgiDavDebugFilter
69
-#from http_authenticator import HTTPAuthenticator
70
-#from error_printer import ErrorPrinter
71
-#middleware_stack = [ WsgiDavDirBrowser, HTTPAuthenticator, ErrorPrinter, WsgiDavDebugFilter ]
72
-
73
-#===============================================================================
74
-# Debugging
75
-
76
-# verbose = 3
77
-
78
-# Enable specific module loggers
79
-# E.g. ["lock_manager", "property_manager", "http_authenticator", ...]
80
-# enable_loggers = ["http_authenticator", ]
81
-
82
-# Enable max. logging for certain http methods
83
-# E.g. ["COPY", "DELETE", "GET", "HEAD", "LOCK", "MOVE", "OPTIONS", "PROPFIND", "PROPPATCH", "PUT", "UNLOCK"]
84
-debug_methods = []
85
-
86
-# Enable max. logging during  litmus suite tests that contain certain strings
87
-# E.g. ["lock_excl", "notowner_modify", "fail_cond_put_unlocked", ...]
88
-debug_litmus = []
89
-
90
-
91
-################################################################################
92
-# WsgiDavDirBrowser
93
-
94
-dir_browser = {
95
-    "enable": True,          # Render HTML listing for GET requests on collections
96
-    "response_trailer": "",  # Raw HTML code, appended as footer
97
-    "davmount": True,        # Send <dm:mount> response if request URL contains '?davmount'
98
-    "ms_mount": True,        # Add an 'open as webfolder' link (requires Windows)
99
-    "ms_sharepoint_plugin": True, # Invoke MS Offce documents for editing using WebDAV
100
-    "ms_sharepoint_urls": False,  # Prepend 'ms-word:ofe|u|' to URL for MS Offce documents
101
-}
102
-
18
+port = 3030
103 19
 
104
-################################################################################
105
-# DAV Provider
106
-
107
-#===============================================================================
108
-# Property Manager
109
-
110
-# Example: Use PERSISTENT shelve based property manager
111
-#from wsgidav.property_manager import ShelvePropertyManager
112
-#propsmanager = ShelvePropertyManager("wsgidav-props.shelve")
20
+show_history = True
21
+show_deleted = True
22
+show_archived = True
113 23
 
114
-### Use in-memory property manager (NOT persistent)
115
-propsmanager = True
116
-
117
-
118
-### Optional additional live property modification
119
-# Enable to allow clients to use e.g. the touch or cp / rsync commands with the
120
-# preserve-timestamp flags in a mounted DAV share (may be RFC4918 incompliant)
121
-#mutable_live_props = ["{DAV:}getlastmodified"]
24
+manager_locks = True
122 25
 
26
+root_path = ''
123 27
 
124 28
 #===============================================================================
125 29
 # Lock Manager
126 30
 #
127 31
 # Example: Use PERSISTENT shelve based lock manager
128 32
 #from wsgidav.lock_storage import LockStorageShelve
129
-#locksmanager = LockStorageShelve("wsgidav-locks.shelve")
130
-
131
-
132
-#===============================================================================
133
-# SHARES
134
-
135
-addShare("", r"~/davshare")
136
-
137
-
138
-################################################################################
139
-# AUTHENTICATION
140
-#===============================================================================
141
-# HTTP Authentication Options
142
-
143
-acceptbasic = True    # Allow basic authentication, True or False
144
-acceptdigest = True   # Allow digest authentication, True or False
145
-defaultdigest = True  # True (default digest) or False (default basic)
146
-
147
-
148
-#domaincontroller =   # Uncomment this line to specify your own domain controller
149
-                      # Default: wsgidav.domain_controller, which uses the USERS 
150
-                      #          section below
151
-
152
-
153
-# Example: use a domain controller that allows users to authenticate against 
154
-#          a Windows NT domain or a local computer.
155
-#          Note: NTDomainController requires basic authentication:
156
-#                Set acceptbasic=True, acceptdigest=False, defaultdigest=False 
157
-
158
-# from wsgidav.addons.nt_domain_controller import NTDomainController
159
-# domaincontroller = NTDomainController(presetdomain=None, presetserver=None)
160
-# acceptbasic = True
161
-# acceptdigest = False
162
-# defaultdigest = False
163
-
164
-
165
-#===============================================================================
166
-# USERS
167
-#
168
-# This section is ONLY used by the DEFAULT Domain Controller.
169
-#
170
-# Users are defined per realm: 
171
-#     addUser(<realm>, <user>, <password>, <description>)  
172
-#
173
-# Note that the default Domain Controller uses the share name as realm name.   
174
-# 
175
-# If no users are specified for a realm, no authentication is required.
176
-# Thus granting read-write access to anonymous! 
177
-#
178
-# Note: If you wish to use Windows WebDAV support (such as Windows XP's My 
179
-# Network Places), you need to include the domain of the user as part of the 
180
-# username (note the DOUBLE slash), such as:
181
-# addUser("v_root", "domain\\user", "password", "description")
182
-
183
-addUser("", "tester", "secret", "")
184
-#addUser("", "tester2", "secret2", "")
33
+#locksmanager = LockStorageShelve("wsgidav-locks.shelve")