diff --git a/puppet/zulip/files/nginx/sites-available/zulip-enterprise b/puppet/zulip/files/nginx/sites-available/zulip-enterprise index b2f3e3a0ecf407..54945171b18905 100644 --- a/puppet/zulip/files/nginx/sites-available/zulip-enterprise +++ b/puppet/zulip/files/nginx/sites-available/zulip-enterprise @@ -12,7 +12,8 @@ server { ssl_certificate /etc/ssl/certs/zulip.combined-chain.crt; ssl_certificate_key /etc/ssl/private/zulip.key; - location /user_uploads { + location /serve_uploads { + internal; add_header X-Content-Type-Options nosniff; include /etc/nginx/zulip-include/uploads.types; alias /home/zulip/uploads/files; diff --git a/requirements/common.txt b/requirements/common.txt index fb6330cc6195fe..d4101ab985f661 100644 --- a/requirements/common.txt +++ b/requirements/common.txt @@ -191,3 +191,8 @@ git+https://github.com/rafaelmartins/pyoembed.git@eb9901917c2a44b49e2887c077ead8 # used in development for some tests and in production for things like # Nagios checks. api/ + +# Needed for serving uploaded files from nginx but perform auth checks in django. +# We are using a commit from a PR https://github.com/johnsensible/django-sendfile/pull/64 +# in Django-sendfile repo as it might be sometime before it gets merged. +git+https://github.com/adnrs96/django-sendfile.git@f45fac5fdd83e7d42a8d5275038e33f8c2cdb920#egg=django-sendfile==0.3.12 diff --git a/zerver/views/upload.py b/zerver/views/upload.py index 0a5f14f1d7c51c..eb38ec66418b38 100644 --- a/zerver/views/upload.py +++ b/zerver/views/upload.py @@ -14,24 +14,19 @@ from zerver.lib.validator import check_bool from zerver.models import UserProfile, validate_attachment_request from django.conf import settings +from sendfile import sendfile def serve_s3(request, url_path): # type: (HttpRequest, str) -> HttpResponse uri = get_signed_upload_url(url_path) return redirect(uri) -# TODO: Rewrite this once we have django-sendfile def serve_local(request, path_id): # type: (HttpRequest, str) -> HttpResponse - import os - import mimetypes local_path = get_local_file_path(path_id) if local_path is None: return HttpResponseNotFound('

File not found

') - filename = os.path.basename(local_path) - response = FileResponse(open(local_path, 'rb'), - content_type = mimetypes.guess_type(filename)) - return response + return sendfile(request, local_path) @has_request_variables def serve_file_backend(request, user_profile, realm_id_str, filename): diff --git a/zproject/dev_settings.py b/zproject/dev_settings.py index 576762e250794d..2ccc028d861814 100644 --- a/zproject/dev_settings.py +++ b/zproject/dev_settings.py @@ -52,3 +52,5 @@ # Don't require anything about password strength in development PASSWORD_MIN_LENGTH = 0 PASSWORD_MIN_ZXCVBN_QUALITY = 0 +# Make sendfile use django to serve files in development +SENDFILE_BACKEND = 'sendfile.backends.development' diff --git a/zproject/prod_settings_template.py b/zproject/prod_settings_template.py index 6fb4ae563afaaf..5e3761c1e7a3fe 100644 --- a/zproject/prod_settings_template.py +++ b/zproject/prod_settings_template.py @@ -166,21 +166,20 @@ # directly on the Zulip server. If file storage in Amazon S3 is # desired, you can configure that as follows: # -# (1) Set s3_key and s3_secret_key in /etc/zulip/zulip-secrets.conf to +# Set s3_key and s3_secret_key in /etc/zulip/zulip-secrets.conf to # be the S3 access and secret keys that you want to use, and setting # the S3_AUTH_UPLOADS_BUCKET and S3_AVATAR_BUCKET to be the S3 buckets # you've created to store file uploads and user avatars, respectively. # Then restart Zulip (scripts/restart-zulip). -# -# (2) Edit /etc/nginx/sites-available/zulip-enterprise to comment out -# the nginx configuration for /user_uploads and /user_avatars (see -# https://github.com/zulip/zulip/issues/291 for discussion of a better -# solution that won't be automatically reverted by the Zulip upgrade -# script), and then restart nginx. LOCAL_UPLOADS_DIR = "/home/zulip/uploads" #S3_AUTH_UPLOADS_BUCKET = "" #S3_AVATAR_BUCKET = "" +# Setup the version of NGINX which is being used for this installation. +# By default a NGINX version greater that 1.5.9 is assumed but if you are using +# a older version, it is necessary to specify it here. +# NGINX_VERSION = '1.4.6' + # Maximum allowed size of uploaded files, in megabytes. DO NOT SET # ABOVE 80MB. The file upload implementation doesn't support chunked # uploads, so browsers will crash if you try uploading larger files. diff --git a/zproject/settings.py b/zproject/settings.py index 33f401c4ac522c..afda0bd806c5cb 100644 --- a/zproject/settings.py +++ b/zproject/settings.py @@ -86,6 +86,9 @@ def get_secret(key): # Import prod_settings after determining the deployment/machine type if PRODUCTION: from .prod_settings import * + SENDFILE_BACKEND = 'sendfile.backends.nginx' + SENDFILE_ROOT = os.path.join(LOCAL_UPLOADS_DIR, 'files') + SENDFILE_URL = '/serve_uploads' else: from .dev_settings import *