@@ -155,6 +155,28 @@ def is_hidden(self, path):
155
155
os_path = self ._get_os_path (path = path )
156
156
return is_hidden (os_path , self .root_dir )
157
157
158
+ def is_writable (self , path ):
159
+ """Does the API style path correspond to a writable directory or file?
160
+
161
+ Parameters
162
+ ----------
163
+ path : string
164
+ The path to check. This is an API path (`/` separated,
165
+ relative to root_dir).
166
+
167
+ Returns
168
+ -------
169
+ hidden : bool
170
+ Whether the path exists and is writable.
171
+ """
172
+ path = path .strip ("/" )
173
+ os_path = self ._get_os_path (path = path )
174
+ try :
175
+ return os .access (os_path , os .W_OK )
176
+ except OSError :
177
+ self .log .error ("Failed to check write permissions on %s" , os_path )
178
+ return False
179
+
158
180
def file_exists (self , path ):
159
181
"""Returns True if the file exists, else returns False.
160
182
@@ -251,12 +273,8 @@ def _base_model(self, path):
251
273
model ["format" ] = None
252
274
model ["mimetype" ] = None
253
275
model ["size" ] = size
276
+ model ["writable" ] = self .is_writable (path )
254
277
255
- try :
256
- model ["writable" ] = os .access (os_path , os .W_OK )
257
- except OSError :
258
- self .log .error ("Failed to check write permissions on %s" , os_path )
259
- model ["writable" ] = False
260
278
return model
261
279
262
280
def _dir_model (self , path , content = True ):
@@ -514,10 +532,12 @@ def is_non_empty_dir(os_path):
514
532
# deleting non-empty files. See Github issue 3631.
515
533
raise web .HTTPError (400 , u"Directory %s not empty" % os_path )
516
534
if _check_trash (os_path ):
517
- self .log .debug ("Sending %s to trash" , os_path )
518
535
# Looking at the code in send2trash, I don't think the errors it
519
536
# raises let us distinguish permission errors from other errors in
520
- # code. So for now, just let them all get logged as server errors.
537
+ # code. So for now, the "look before you leap" approach is used.
538
+ if not self .is_writable (path ):
539
+ raise web .HTTPError (403 , u"Permission denied: %s" % path )
540
+ self .log .debug ("Sending %s to trash" , os_path )
521
541
send2trash (os_path )
522
542
return
523
543
else :
@@ -842,10 +862,12 @@ async def is_non_empty_dir(os_path):
842
862
# deleting non-empty files. See Github issue 3631.
843
863
raise web .HTTPError (400 , u"Directory %s not empty" % os_path )
844
864
if await _check_trash (os_path ):
845
- self .log .debug ("Sending %s to trash" , os_path )
846
865
# Looking at the code in send2trash, I don't think the errors it
847
866
# raises let us distinguish permission errors from other errors in
848
- # code. So for now, just let them all get logged as server errors.
867
+ # code. So for now, the "look before you leap" approach is used.
868
+ if not self .is_writable (path ):
869
+ raise web .HTTPError (403 , u"Permission denied: %s" % path )
870
+ self .log .debug ("Sending %s to trash" , os_path )
849
871
send2trash (os_path )
850
872
return
851
873
else :
0 commit comments