Repository: CTFd/CTFd

Issue:
The REST API for deleting files does not remove the file's directory and does not update the Media Library list
**Environment**: 

- CTFd Version/Commit: 3.2.1
- Operating System: Docker (`python:3.6-slim-buster`)
- Web Browser and Version: NA

**What happened?**

I am using the REST API for deleting files (e.g. `"DELETE /api/v1/files/41 HTTP/1.1"`) and it seems to work fine. The file is removed. However, two things do go wrong I think (at least to my expectation).

1. The file's directory (which has a hash based name) is not deleted. This means, after a while there will be a lot of empty directories.
1. The list of files used by the Media Library is not updated (i.e. file is removed from the list) which means the list grows constantly. The result is a list with many non-existing files as they are deleted.

The REST API returns a successful `200` code which seems to match with the expected behaviour.

**What did you expect to happen?**

When a file is deleted using the REST API, I expect the directory (the hash-based name) to be deleted and that the list used by the Media Library is updated accordingly.

**How to reproduce your issue**

1. Upload a file (e.g. via the web interface or REST API). 
1. Use the REST API to delete this file.
1. Check the `upload/` folder and the Media Library for the behaviour described above.

**Any associated stack traces or error logs**

None



Discussion:
I think not removing the directory was some old (likely dumb) design decision I made. It should be revisited for the reasons you mentioned above. 

However the list of files in the MediaLibrary should be being updated.... The code explicitly deletes the database row. https://github.com/CTFd/CTFd/blob/eabf43f9809546a5c30865e51694a02f72d11b8b/CTFd/api/v1/files.py#L131-L144

Does deleting via the web UI do the right thing? 
> Does deleting via the web UI do the right thing?

Yes, deleting via the web UI always worked as expected afaik.

I just tried to reproduce the problem but it seems the behaviour is now as expected. For now I am unable to reproduce the problem. Therefore, it's unclear to me how I ended up with duplicates in the Media Library list as I assumed the REST API was simply not updating the list. It seems the issue is a bit more nuanced (or may even be caused by how I use the REST API).

This issue was also present for me on older versions of CTFd; I only recently updated to 3.2.1. I will come back here once I face the issue again and know hopefully better how to reproduce it.

Resolving patch:
diff --git a/CTFd/utils/uploads/uploaders.py b/CTFd/utils/uploads/uploaders.py
--- a/CTFd/utils/uploads/uploaders.py
+++ b/CTFd/utils/uploads/uploaders.py
@@ -1,7 +1,8 @@
 import os
 import posixpath
 import string
-from shutil import copyfileobj
+from pathlib import PurePath
+from shutil import copyfileobj, rmtree
 
 import boto3
 from flask import current_app, redirect, send_file
@@ -64,7 +65,8 @@ def download(self, filename):
 
     def delete(self, filename):
         if os.path.exists(os.path.join(self.base_path, filename)):
-            os.unlink(os.path.join(self.base_path, filename))
+            file_path = PurePath(filename).parts[0]
+            rmtree(os.path.join(self.base_path, file_path))
             return True
         return False
 


Test patch: