Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #13518 -- Added FILE_UPLOAD_DIRECTORY_PERMISSIONS setting

This setting does for new directories what FILE_UPLOAD_PERMISSIONS
does for new files.

Thanks jacob@ for the suggestion.
  • Loading branch information...
commit 6bdb3b1135d1bd7b2dc24131b9d26ac19ebdba67 1 parent ab68072
raumkraut authored May 13, 2013 timgraham committed August 12, 2013
5  django/conf/global_settings.py
@@ -313,6 +313,11 @@
313 313
 # you'd pass directly to os.chmod; see http://docs.python.org/lib/os-file-dir.html.
314 314
 FILE_UPLOAD_PERMISSIONS = None
315 315
 
  316
+# The numeric mode to assign to newly-created directories, when uploading files.
  317
+# The value should be a mode as you'd pass to os.chmod;
  318
+# see http://docs.python.org/lib/os-file-dir.html.
  319
+FILE_UPLOAD_DIRECTORY_PERMISSIONS = None
  320
+
316 321
 # Python module path where user will place custom format definition.
317 322
 # The directory where this setting is pointing should contain subdirectories
318 323
 # named as the locales, containing a formats.py file
11  django/core/files/storage.py
@@ -172,7 +172,16 @@ def _save(self, name, content):
172 172
         directory = os.path.dirname(full_path)
173 173
         if not os.path.exists(directory):
174 174
             try:
175  
-                os.makedirs(directory)
  175
+                if settings.FILE_UPLOAD_DIRECTORY_PERMISSIONS is not None:
  176
+                    # os.makedirs applies the global umask, so we reset it,
  177
+                    # for consistency with FILE_UPLOAD_PERMISSIONS behavior.
  178
+                    old_umask = os.umask(0)
  179
+                    try:
  180
+                        os.makedirs(directory, settings.FILE_UPLOAD_DIRECTORY_PERMISSIONS)
  181
+                    finally:
  182
+                        os.umask(old_umask)
  183
+                else:
  184
+                    os.makedirs(directory)
176 185
             except OSError as e:
177 186
                 if e.errno != errno.EEXIST:
178 187
                     raise
13  docs/ref/settings.txt
@@ -1108,6 +1108,19 @@ Default: ``2621440`` (i.e. 2.5 MB).
1108 1108
 The maximum size (in bytes) that an upload will be before it gets streamed to
1109 1109
 the file system. See :doc:`/topics/files` for details.
1110 1110
 
  1111
+.. setting:: FILE_UPLOAD_DIRECTORY_PERMISSIONS
  1112
+
  1113
+FILE_UPLOAD_DIRECTORY_PERMISSIONS
  1114
+---------------------------------
  1115
+
  1116
+.. versionadded:: 1.7
  1117
+
  1118
+Default: ``None``
  1119
+
  1120
+The numeric mode to apply to directories created in the process of
  1121
+uploading files. This value mirrors the functionality and caveats of
  1122
+the :setting:`FILE_UPLOAD_PERMISSIONS` setting.
  1123
+
1111 1124
 .. setting:: FILE_UPLOAD_PERMISSIONS
1112 1125
 
1113 1126
 FILE_UPLOAD_PERMISSIONS
4  docs/releases/1.7.txt
@@ -138,6 +138,10 @@ Minor features
138 138
 * The :func:`~django.contrib.auth.decorators.permission_required` decorator can
139 139
   take a list of permissions as well as a single permission.
140 140
 
  141
+* The new :setting:`FILE_UPLOAD_DIRECTORY_PERMISSIONS` setting controls
  142
+  the file system permissions of directories created during file upload, like
  143
+  :setting:`FILE_UPLOAD_PERMISSIONS` does for the files themselves.
  144
+
141 145
 Backwards incompatible changes in 1.7
142 146
 =====================================
143 147
 
7  docs/topics/http/file-uploads.txt
@@ -132,7 +132,7 @@ upload behavior.
132 132
 Changing upload handler behavior
133 133
 --------------------------------
134 134
 
135  
-Three settings control Django's file upload behavior:
  135
+There are a few settings which control Django's file upload behavior:
136 136
 
137 137
 :setting:`FILE_UPLOAD_MAX_MEMORY_SIZE`
138 138
     The maximum size, in bytes, for files that will be uploaded into memory.
@@ -167,6 +167,11 @@ Three settings control Django's file upload behavior:
167 167
 
168 168
         **Always prefix the mode with a 0.**
169 169
 
  170
+:setting:`FILE_UPLOAD_DIRECTORY_PERMISSIONS`
  171
+    The numeric mode to apply to directories created in the process of
  172
+    uploading files. This value mirrors the functionality and caveats of
  173
+    the :setting:`FILE_UPLOAD_PERMISSIONS` setting.
  174
+
170 175
 :setting:`FILE_UPLOAD_HANDLERS`
171 176
     The actual handlers for uploaded files. Changing this setting allows
172 177
     complete customization -- even replacement -- of Django's upload
12  tests/file_storage/tests.py
@@ -462,6 +462,18 @@ def test_file_upload_default_permissions(self):
462 462
         mode = os.stat(self.storage.path(fname))[0] & 0o777
463 463
         self.assertEqual(mode, 0o666 & ~self.umask)
464 464
 
  465
+    @override_settings(FILE_UPLOAD_DIRECTORY_PERMISSIONS=0o765)
  466
+    def test_file_upload_directory_permissions(self):
  467
+        name = self.storage.save("the_directory/the_file", ContentFile("data"))
  468
+        dir_mode = os.stat(os.path.dirname(self.storage.path(name)))[0] & 0o777
  469
+        self.assertEqual(dir_mode, 0o765)
  470
+
  471
+    @override_settings(FILE_UPLOAD_DIRECTORY_PERMISSIONS=None)
  472
+    def test_file_upload_directory_default_permissions(self):
  473
+        name = self.storage.save("the_directory/the_file", ContentFile("data"))
  474
+        dir_mode = os.stat(os.path.dirname(self.storage.path(name)))[0] & 0o777
  475
+        self.assertEqual(dir_mode, 0o777 & ~self.umask)
  476
+
465 477
 class FileStoragePathParsing(unittest.TestCase):
466 478
     def setUp(self):
467 479
         self.storage_dir = tempfile.mkdtemp()

0 notes on commit 6bdb3b1

Please sign in to comment.
Something went wrong with that request. Please try again.