Skip to content

Commit

Permalink
proxy avatars from s3 storage
Browse files Browse the repository at this point in the history
  • Loading branch information
fiorda committed Sep 7, 2018
1 parent c6504e1 commit 8024dfc
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 8 deletions.
14 changes: 8 additions & 6 deletions pybossa/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,20 +145,22 @@ def setup_uploader(app):
"""Setup uploader."""
global uploader

if app.config.get('UPLOAD_METHOD') == 'local':
upload_method = app.config.get('UPLOAD_METHOD')
if upload_method == 'local':
from pybossa.uploader.local import LocalUploader
uploader = LocalUploader()
uploader.init_app(app)
if app.config.get('UPLOAD_METHOD') == 'rackspace': # pragma: no cover
if upload_method == 'rackspace': # pragma: no cover
from pybossa.uploader.rackspace import RackspaceUploader
uploader = RackspaceUploader()
app.url_build_error_handlers.append(uploader.external_url_handler)
uploader.init_app(app)
if app.config.get('UPLOAD_METHOD') == 'cloud': # pragma: no cover
if upload_method == 'cloud': # pragma: no cover
from pybossa.uploader.cloud_store import CloudStoreUploader
uploader = CloudStoreUploader()
app.url_build_error_handlers.append(uploader.external_url_handler)
uploader.init_app(app)
if upload_method == 'cloudproxy': #pragma: no cover
from pybossa.uploader.cloud_proxy import CloudProxyUploader
uploader = CloudProxyUploader()
uploader.init_app(app)


def setup_exporter(app):
Expand Down
3 changes: 3 additions & 0 deletions pybossa/uploader/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,6 @@ def delete_file(self, name, container): # pragma: no cover
def file_exists(self, name, container): #pragma: no cover
"""Override by the uploader handler."""
pass

def send_file(self, filename):
pass
20 changes: 20 additions & 0 deletions pybossa/uploader/cloud_proxy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from flask import Response, current_app
from pybossa.uploader.cloud_store import CloudStoreUploader


MAX_AGE = 356 * 24 * 60 * 60


class CloudProxyUploader(CloudStoreUploader):

def send_file(self, filename):
try:
key = self.bucket.get_key(filename, validate=False)
content = key.get_contents_as_string()
response = Response(content, content_type=key.content_type)
response.cache_control.max_age = MAX_AGE
response.cache_control.public = True
except Exception as e:
current_app.logger.exception(e)
return Response('Not Found', 404)
return response
3 changes: 3 additions & 0 deletions pybossa/uploader/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"""
from pybossa.uploader import Uploader
import os
from flask import send_from_directory
from werkzeug import secure_filename


Expand Down Expand Up @@ -91,3 +92,5 @@ def get_file_path(self, container, filename):
return os.path.join(
self.get_container_path(container), filename)

def send_file(self, filename):
return send_from_directory(self.upload_folder, filename)
4 changes: 2 additions & 2 deletions pybossa/view/uploads.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
This module serves uploaded content like avatars.
"""
from flask import Blueprint, send_from_directory
from flask import Blueprint
from pybossa.core import uploader


Expand All @@ -31,4 +31,4 @@
@blueprint.route('/<path:filename>')
def uploaded_file(filename): # pragma: no cover
"""Return uploaded file."""
return send_from_directory(uploader.upload_folder, filename)
return uploader.send_file(filename)
50 changes: 50 additions & 0 deletions test/test_uploader/test_cloud_uploader.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

from default import Test, with_context
from pybossa.uploader.cloud_store import CloudStoreUploader
from pybossa.uploader.cloud_proxy import CloudProxyUploader
from mock import patch, PropertyMock, call, MagicMock
from werkzeug.datastructures import FileStorage
from io import StringIO
Expand Down Expand Up @@ -149,3 +150,52 @@ def test_failover_url(self):
}
url = u.external_url_handler(None, None, values)
assert url.endswith('{}/static/img/placeholder.project.png'.format(self.flask_app.config['SERVER_NAME'])), url


class TestCloudProxyUploader(Test):

conn_args = {
'host': 's3.com',
'headers': True
}

@with_context
@patch('pybossa.uploader.cloud_store.create_connection')
def test_cloud_proxy_uploader(self, create_connection):
mock_conn = MagicMock()
mock_bucket = MagicMock()
mock_key = MagicMock()
mock_conn.get_bucket.return_value = mock_bucket
mock_bucket.get_key.return_value = mock_key

create_connection.return_value = mock_conn
u = CloudProxyUploader()

mock_key.get_contents_as_string.return_value = 'hello world'
with patch.dict(self.flask_app.config, {
'UPLOAD_BUCKET': 'testbucket',
'S3_UPLOAD': self.conn_args
}):
response = u.send_file('test.png')
assert response.status_code == 200
assert response.data == 'hello world'

@with_context
@patch('pybossa.uploader.cloud_store.create_connection')
def test_cloud_proxy_uploader_not_found(self, create_connection):
mock_conn = MagicMock()
mock_bucket = MagicMock()
mock_key = MagicMock()
mock_conn.get_bucket.return_value = mock_bucket
mock_bucket.get_key.return_value = mock_key

create_connection.return_value = mock_conn
u = CloudProxyUploader()

mock_key.get_contents_as_string.side_effect = Exception
with patch.dict(self.flask_app.config, {
'UPLOAD_BUCKET': 'testbucket',
'S3_UPLOAD': self.conn_args
}):
response = u.send_file('test.png')
assert response.status_code == 404

0 comments on commit 8024dfc

Please sign in to comment.