Просмотр исходного кода

correction of some behavior and bugs

Nonolost 7 лет назад
Родитель
Сommit
596e13361c

+ 1 - 0
.gitignore Просмотреть файл

@@ -60,5 +60,6 @@ tracim/data/
60 60
 # Site-local config file
61 61
 development.ini
62 62
 track.js
63
+wsgidav.conf
63 64
 # Temporary files
64 65
 *~

+ 24 - 16
install/requirements.txt Просмотреть файл

@@ -1,51 +1,53 @@
1
-Babel==2.2.0
2
-Beaker==1.6.4
3
-CherryPy==3.6.0
4
-FormEncode==1.3.0a1
5
-Genshi==0.7
6
-Mako==1.0.3
7
-MarkupSafe==0.23
8
-PasteDeploy==1.5.2
9
-Radicale==1.1.1
10
-SQLAlchemy==1.0.11
11
-Tempita==0.5.3dev
12
-TurboGears2==2.3.7
13
-Unidecode==0.04.19
14
-WebOb==1.6.0a0
15
-WebTest==1.4.2
16 1
 alembic==0.8.4
17
-argparse==1.2.1
2
+Babel==2.2.0
18 3
 backlash==0.0.7
4
+Beaker==1.6.4
19 5
 beautifulsoup4==4.3.2
6
+Brlapi==0.6.2
20 7
 caldav==0.4.0
8
+chardet==2.3.0
9
+CherryPy==3.6.0
21 10
 cliff==1.8.0
22 11
 cmd2==0.6.7
23 12
 coverage==4.0b1
24 13
 crank==0.7.3
25 14
 decorator==3.4.0
15
+FormEncode==1.3.0a1
26 16
 gearbox==0.0.7
17
+Genshi==0.7
27 18
 icalendar==3.10
28 19
 itsdangerous==0.24
29 20
 ldap3==1.3.1
21
+louis==2.5.3
30 22
 lxml==3.6.0
23
+Mako==1.0.3
24
+MarkupSafe==0.23
31 25
 nose==1.3.4
26
+PasteDeploy==1.5.2
32 27
 pbr==0.10.0
33 28
 prettytable==0.7.2
34 29
 psycopg2==2.5.4
35 30
 py4j==0.10.1
36 31
 pyasn1==0.1.9
32
+pygobject==3.14.0
37 33
 pyparsing==2.0.3
34
+python-apt==0.9.3.12
38 35
 python-dateutil==2.5.3
36
+python-debian==0.1.27
39 37
 python-editor==1.0.1
40 38
 python-ldap-test==0.2.1
41 39
 pytz==2014.7
40
+pyxdg==0.25
41
+Radicale==1.1.1
42 42
 repoze.lru==0.6
43 43
 repoze.who==2.2
44 44
 requests==2.10.0
45 45
 six==1.8.0
46 46
 speaklater==1.3
47 47
 sprox==0.9.4
48
+SQLAlchemy==1.0.11
48 49
 stevedore==1.1.0
50
+Tempita==0.5.3.dev0
49 51
 tg.devtools==2.3.7
50 52
 tgapp-resetpassword==0.1.8
51 53
 tgext.admin==0.6.4
@@ -53,11 +55,17 @@ tgext.asyncjob==0.3.1
53 55
 tgext.crud==0.7.3
54 56
 tgext.pluggable==0.5.5
55 57
 transaction==1.4.4
58
+TurboGears2==2.3.7
56 59
 tw2.core==2.2.2
57 60
 tw2.forms==2.2.2.1
58 61
 unicode-slugify==0.1.3
62
+Unidecode==0.4.19
63
+virtualenv==1.11.6
59 64
 vobject==0.9.2
60 65
 waitress==0.8.9
66
+WebOb==1.6.0a0
67
+WebTest==1.4.2
61 68
 who-ldap==3.1.0
69
+-e git+git@github.com:mar10/wsgidav.git@e233fc4f5f23d1b5326159dfecd39990088f3fbc#egg=WsgiDAV
62 70
 zope.interface==4.1.3
63 71
 zope.sqlalchemy==0.7.6

+ 2 - 0
tracim/tracim/config/app_cfg.py Просмотреть файл

@@ -31,6 +31,7 @@ from tracim.lib.auth.wrapper import AuthConfigWrapper
31 31
 from tracim.lib.base import logger
32 32
 from tracim.lib.daemons import DaemonsManager
33 33
 from tracim.lib.daemons import RadicaleDaemon
34
+from tracim.lib.daemons import WsgiDavDaemon
34 35
 from tracim.model.data import ActionDescription
35 36
 from tracim.model.data import ContentType
36 37
 
@@ -95,6 +96,7 @@ def start_daemons(manager: DaemonsManager):
95 96
     Sart Tracim daemons
96 97
     """
97 98
     manager.run('radicale', RadicaleDaemon)
99
+    manager.run('webdav', WsgiDavDaemon)
98 100
 
99 101
 environment_loaded.register(lambda: start_daemons(daemons))
100 102
 

+ 2 - 2
tracim/tracim/lib/content.py Просмотреть файл

@@ -402,8 +402,8 @@ class ContentApi(object):
402 402
         if content_type!=ContentType.Any:
403 403
             resultset = resultset.filter(Content.type==content_type)
404 404
 
405
-        if parent_id:
406
-            resultset = resultset.filter(Content.parent_id==parent_id)
405
+        # todo : check utilité if parent_id:
406
+        resultset = resultset.filter(Content.parent_id==parent_id)
407 407
 
408 408
         return resultset.all()
409 409
 

+ 42 - 20
tracim/tracim/lib/webdav/sql_resources.py Просмотреть файл

@@ -123,11 +123,15 @@ class Workspace(DAVCollection):
123 123
 
124 124
     def getMember(self, content_label):
125 125
 
126
+        if content_label=='':
127
+            return None
128
+
126 129
         content = self._api.get_one_by_label_and_parent(
127 130
             content_label=content_label,
128 131
             workspace=self._workspace
129 132
         )
130 133
 
134
+        print("ok : ", content_label)
131 135
         return Folder(self.path + content.get_label(), self.environ, content)
132 136
 
133 137
     def createEmptyResource(self, name):
@@ -709,15 +713,24 @@ class File(DAVNonCollection):
709 713
         if dirname(destpath).endswith('.deleted') or dirname(destpath).endswith('.archived'):
710 714
             if basename(dirname(dirname(destpath))) == self._content.parent.label:
711 715
                 if dirname(destpath).endswith('.deleted'):
716
+                    if self._content.label != '':
717
+                        self._content.label += 'deleted now'
718
+                    else:
719
+                        self._content.file_name += 'deleted now'
712 720
                     Encapsuler(ActionDescription.DELETION, self._api, self._content).action()
713 721
                 else:
714 722
                     Encapsuler(ActionDescription.ARCHIVING, self._api, self._content).action()
723
+                    if self._content.label != '':
724
+                        self._content.label += 'archived now'
725
+                    else:
726
+                        self._content.file_name += 'archived now'
715 727
             else:
716 728
                 raise DAVError(HTTP_FORBIDDEN)
717 729
         elif (dirname(npath).endswith('.deleted') or dirname(npath).endswith('.archived')):
718 730
             if dirname(dirname(npath)) == dirname(destpath):
719 731
                 if dirname(npath).endswith('.deleted'):
720 732
                     Encapsuler(ActionDescription.UNDELETION, self._api, self._content).action()
733
+                    
721 734
                 else:
722 735
                     Encapsuler(ActionDescription.UNARCHIVING, self._api, self._content).action()
723 736
             else:
@@ -842,22 +855,21 @@ class OtherFile(File):
842 855
                 label = _LABELS[event.type.id]
843 856
 
844 857
                 histHTML += '''
845
-                <tr>
858
+                <tr class="%s">
846 859
                     <td class="my-align"><span class="label label-default"><i class="fa %s"></i> %s</span></td>
847 860
                     <td>%s</td>
848 861
                     <td>%s</td>
849 862
                     <td>%s</td>
850 863
                 </tr>
851
-                ''' % (event.type.icon,
864
+                ''' % ('warning' if event.id == content.revision_id else '',
865
+                       event.type.icon,
852 866
                        label,
853 867
                        date,
854 868
                        event.owner.display_name,
855
-                       '''<span><a href="#">View revision</a></span>''' if event.type.id == 'revision' else '')
869
+                       '<i class="fa fa-caret-left"></i> shown' if event.id == content.revision_id else '''<span><a class="revision-link" href="/.history/%s/%s-%s">(View revision)</a></span>''' % (self._content.label, event.id, event.ref_object.label) if event.type.id == 'revision' else '')
856 870
 
857 871
         histHTML+='</table>'
858 872
 
859
-        #pdf = pdfkit.from_string(self._content.description, False)
860
-
861 873
         file = '''
862 874
 <html>
863 875
 <head>
@@ -877,11 +889,8 @@ class OtherFile(File):
877 889
             </div>
878 890
             <div class="pull-right">
879 891
                 <div class="btn-group btn-group-vertical">
880
-                    <a class="btn btn-default" onclick="download_pdf()">
881
-                        <i class="fa fa-download"></i> Download as pdf</a>
882
-                    </a>
883 892
                     <a class="btn btn-default">
884
-                        <i class="fa fa-external-link"></i> Access webdav</a>
893
+                        <i class="fa fa-external-link"></i> View in tracim</a>
885 894
                     </a>
886 895
                 </div>
887 896
             </div>
@@ -894,9 +903,14 @@ class OtherFile(File):
894 903
         <h4>History</h4>
895 904
         %s
896 905
     </div>
897
-    <script>
898
-        function download_pdf() {
899
-            download("%s", "%s.pdf", "application/pdf")
906
+    <script type="text/javascript">
907
+        window.onload = function() {
908
+            elems = document.getElementsByClassName('revision-link');
909
+            for(var i = 0; i<elems.length; i++) {
910
+                test = window.location.href
911
+                test += "/.." + elems[i].href.replace(/file:\/\//, "")
912
+                elems[i].href = test
913
+            }
900 914
         }
901 915
     </script>
902 916
 </body>
@@ -906,9 +920,7 @@ class OtherFile(File):
906 920
                self._content.created.strftime("%B %d, %Y at %H:%m"),
907 921
                self._content.owner.display_name,
908 922
                content.description,
909
-               histHTML,
910
-               "Meh.",
911
-               self._content.label)
923
+               histHTML)
912 924
 
913 925
         return file
914 926
 
@@ -976,7 +988,10 @@ class OtherFile(File):
976 988
                            t.owner.display_name,
977 989
                            create_readable_date(t.created),
978 990
                            label,
979
-                           '''<span><a href="#">(View revision)</a></span>''' if t.type.id == 'revision' else '')
991
+                           '''<span><a class="revision-link" href="/.history/%s/%s-%s">(View revision)</a></span>''' % (
992
+                               self._content.label,
993
+                               t.id,
994
+                               t.ref_object.label) if t.type.id == 'revision' else '')
980 995
 
981 996
         descP = ''
982 997
         for name, infos in participants.items():
@@ -1006,11 +1021,8 @@ class OtherFile(File):
1006 1021
             </div>
1007 1022
             <div class="pull-right">
1008 1023
                 <div class="btn-group btn-group-vertical">
1009
-                    <a class="btn btn-default" onclick="download_pdf()">
1010
-                        <i class="fa fa-download"></i> Download as pdf</a>
1011
-                    </a>
1012 1024
                     <a class="btn btn-default">
1013
-                        <i class="fa fa-external-link"></i> Access webdav</a>
1025
+                        <i class="fa fa-external-link"></i> View in tracim</a>
1014 1026
                     </a>
1015 1027
                 </div>
1016 1028
             </div>
@@ -1026,6 +1038,16 @@ class OtherFile(File):
1026 1038
         <h4>Participants</h4>
1027 1039
         %s
1028 1040
     </div>
1041
+    <script type="text/javascript">
1042
+        window.onload = function() {
1043
+            elems = document.getElementsByClassName('revision-link');
1044
+            for(var i = 0; i<elems.length; i++) {
1045
+                test = window.location.href
1046
+                test += "/.." + elems[i].href.replace(/file:\/\//, "")
1047
+                elems[i].href = test
1048
+            }
1049
+        }
1050
+    </script>
1029 1051
 </body>
1030 1052
 </html>
1031 1053
         ''' % (content.label,

+ 2 - 1
tracim/tracim/model/data.py Просмотреть файл

@@ -1203,7 +1203,8 @@ class VirtualEvent(object):
1203 1203
 
1204 1204
         label = content.get_label()
1205 1205
         if content.type==ContentType.Comment:
1206
-            label = _('<strong>{}</strong> wrote:').format(content.owner.get_display_name())
1206
+            # todo :voir le _('.... si le _ est utile
1207
+            label = ('<strong>{}</strong> wrote:').format(content.owner.get_display_name())
1207 1208
 
1208 1209
         return VirtualEvent(id=content.content_id,
1209 1210
                             created=content.created,

+ 184 - 0
tracim/wsgidav.conf.sample Просмотреть файл

@@ -0,0 +1,184 @@
1
+################################################################################
2
+# Sample WsgiDAV configuration file
3
+# 
4
+# 1. Rename this file to `wsgidav.conf`
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.
11
+#
12
+################################################################################
13
+
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
+################################################################################
32
+# SERVER OPTIONS
33
+#===============================================================================
34
+
35
+# host  = "localhost"
36
+# host  = "192.168.0.1"
37
+host  = "0.0.0.0"
38
+
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
+
103
+
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")
113
+
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"]
122
+
123
+
124
+#===============================================================================
125
+# Lock Manager
126
+#
127
+# Example: Use PERSISTENT shelve based lock manager
128
+#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", "")