Allow specification of GS_LOCATION for placing assets in subdirectory.
@@ -82,6 +82,7 @@ class GoogleCloudStorage(Storage):
project_id = setting('GS_PROJECT_ID', None)
credentials = setting('GS_CREDENTIALS', None)
bucket_name = setting('GS_BUCKET_NAME', None)
+ location = setting('GS_LOCATION', '')
auto_create_bucket = setting('GS_AUTO_CREATE_BUCKET', False)
auto_create_acl = setting('GS_AUTO_CREATE_ACL', 'projectPrivate')
file_name_charset = setting('GS_FILE_NAME_CHARSET', 'utf-8')
@@ -97,6 +98,7 @@ class GoogleCloudStorage(Storage):
if hasattr(self, name):
setattr(self, name, value)
+ self.location = (self.location or '').lstrip('/')
self._bucket = None
self._client = None
@@ -135,9 +137,14 @@ class GoogleCloudStorage(Storage):
"""
Normalizes the name so that paths like /path/to/ignored/../something.txt
and ./file.txt work. Note that clean_name adds ./ to some paths so
- they need to be fixed here.
+ they need to be fixed here. We check to make sure that the path pointed
+ to is not outside the directory specified by the LOCATION setting.
"""
- return safe_join('', name)
+ try:
+ return safe_join(self.location, name)
+ except ValueError:
+ raise SuspiciousOperation("Attempted access to '%s' denied." %
+ name)
def _encode_name(self, name):
return smart_str(name, encoding=self.file_name_charset)
